UVa 11552 最小的块数(序列划分模型:状态设计)

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
",ans);
70     }
71     return 0;
72 }
原文地址:https://www.cnblogs.com/zyb993963526/p/6921268.html