标签:赋值 iostream href cst return pre char pll class
https://vjudge.net/problem/UVA-11552
题意:
输入一个正整数k和字符串S,字符串的长度保证为k的倍数。把S的字符按照从左到右的顺序每k个分成一组,每组之间可以任意重排,但组与组之间的先后顺序应保持不变。你的任务是让重排后的字符串包含尽量少的“块”,其中每个块为连续的相同字母。
思路:
令d【i】【j】表示第i组中第j位为末尾时的最小块数。
对于第【i】组,我们首先计算出它的块数,即不同字母的个数。
接下来枚举【i】组中第j个字母作为末尾时的情况,根据第【i-1】组中的字母,如果【i-1】中有和第【i】组相同的字母,此时如果【i】组只有一个块或者相同的字母不在【i】组末尾时:
d[i][j]=min(d[i][j],d[i-1][p]+chunk-1);
这样就可以前后相同的相连,减少一个块。
没有相同的字母的话那就只能是两者块相加了:
d[i][j]=min(d[i][j],d[i-1][p]+chunk);
1 #include<iostream> 2 #include<algorithm> 3 #include<cstring> 4 #include<cstdio> 5 #include<sstream> 6 #include<vector> 7 #include<stack> 8 #include<queue> 9 #include<cmath> 10 #include<map> 11 using namespace std; 12 typedef long long LL; 13 typedef pair<int,int> pll; 14 const int INF=0x3f3f3f3f; 15 const int maxn=1000+5; 16 17 int k; 18 char str[maxn]; 19 int d[maxn][maxn]; 20 int vis[150]; 21 22 int main() 23 { 24 //freopen("D:\\input.txt","r",stdin); 25 int T; 26 scanf("%d",&T); 27 while(T--) 28 { 29 scanf("%d",&k); 30 scanf("%s",&str); 31 int len=strlen(str); 32 memset(d,INF,sizeof(d)); 33 34 for(int i=0;i<len/k;i++) 35 { 36 memset(vis,0,sizeof(vis)); 37 for(int j=0;j<k;j++) 38 { 39 int t=i*k+j; 40 vis[str[t]]=1; 41 } 42 43 int chunk=0; 44 for(int c=‘a‘;c<=‘z‘;c++) 45 if(vis[c]) chunk++; 46 47 if(i==0) //第一组的话直接赋值 48 for(int j=0;j<k;j++) 49 d[i][j]=chunk; 50 else 51 { 52 for(int j=0;j<k;j++) 53 { 54 int t=i*k+j; 55 for(int p=0;p<k;p++) //考虑第i-1组的各个字母 56 { 57 int pre=(i-1)*k+p; 58 if(vis[str[pre]] && (chunk==1||str[pre]!=str[t])) 59 d[i][j]=min(d[i][j],d[i-1][p]+chunk-1); 60 else d[i][j]=min(d[i][j],d[i-1][p]+chunk); 61 } 62 } 63 } 64 } 65 66 int ans=INF; 67 for(int i=0;i<k;i++) 68 ans=min(ans,d[len/k-1][i]); 69 printf("%d\n",ans); 70 } 71 return 0; 72 }
标签:赋值 iostream href cst return pre char pll class
原文地址:http://www.cnblogs.com/zyb993963526/p/6921268.html