1 条题解
-
0
[USACO21JAN] Uddered but not Herd G
首先考虑一个问题,如果字母表已经确定,如何将原串分割是最优的。
设原串为 ,原串中字母共有 种,我们认为各个字符之间是可以比较的,在确定的字母表中,靠前的字母比靠后的字母小。
对于原串 ,若有 显然 和 是要被“分割”开的
也就是说,对于这个确定的字母表, 和 不会在同一个周期被念出来, 对答案的贡献为 。
观察数据范围,发现 ,这个数据范围是可以状压的,设集合 表示当前加入的字母的集合, 表示 集合中的字母对答案的贡献的最小值为多少。
维护向集合 中加入字母 的过程,根据我们上面得出的结论, 的贡献就是集合 中满足字符位置为 在原串中的下一位且小于等于 的字符个数(相同的字符可能有多个位置满足要求),这个是可以预处理出来的。
于是根据上面的过程,我们可以得到状态转移方程:
$$f_S=\min_{c_j \in S}\{f_{S\backslash \{c_j\}}+\sum_{c_k \in S} cost_{j,k}\}$$令初始状态为 ,因为要将第一次念字母表计算进去,最终答案为 。
其中 表示在原串中所有 的位置中满足 且 为 的下一位的个数,将原串 离散化之后可以预处理出来。
时间复杂度: 。
既然你能找到这题,我相信你能瞬间做出来的。
Code:#include<bits/stdc++.h> typedef long long LL; typedef long double LD; using namespace std; const int N=21,M=100010,INF=0x3f3f3f3f; inline int Max(int x,int y){return x>y?x:y;} inline int Min(int x,int y){return x<y?x:y;} inline void Swap(int &x,int &y){x^=y^=x^=y;} int n,m,ans=INF,f[1<<20],a[M],b[M],c[N][N]; char s[M]; int main(){ scanf("%s",s+1); n=strlen(s+1); for(int i=1;i<=n;i++)b[i]=s[i]; sort(b+1,b+n+1); int m=unique(b+1,b+n+1)-b-1; for(int i=1;i<=n;i++) a[i]=lower_bound(b+1,b+m+1,s[i])-b-1; for(int i=1;i<n;i++)c[a[i]][a[i+1]]++; memset(f,0x3f,sizeof(f));f[0]=1; for(int S=1;S<(1<<m);S++) for(int j=0;j<m;j++) if(S&1<<j){ int sum=f[S^1<<j]; for(int k=0;k<m;k++) if(S&1<<k)sum+=c[j][k]; f[S]=Min(f[S],sum); } printf("%d\n",f[(1<<m)-1]); return 0; }
- 1
信息
- ID
- 7063
- 时间
- 2000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者