UVA 11552Fewest Flops 【区间dp】

来源:互联网 发布:mvvm数据绑定原理 编辑:程序博客网 时间:2024/05/22 07:53

题意:将一个字符串分成若干块,每块大小为k,保证串的长度是k的倍数。

每块的元素可以任意摆放,但是块与块之间的位置不变。摆放完后,将连续相同的字符看成一个,问最少多少个。

分析:定义dp[i][j]为第i块以该块的第j个元素结尾。

状态转移:

dp[i][j]=min(dp[i][j],dp[i-1][p]+cnt-1);//如果前一块以p结尾,而第i块不以p结尾,那么这里就可以合并一种字符。

dp[i][j]=min(dp[i][j],dp[i-1][p]+cnt);//其他不能合并情况。

cnt是当前字符种数。

代码:

#include<algorithm>#include<iostream>#include<cstring>#include<cstdio>#include<string>#include<vector>#include<queue>#include<cmath>#include<stack>#include<set>#include<map>#define INF 0x3f3f3f3f#define Mn 1005#define Mm 2000005#define mod 1000000007#define CLR(a,b) memset((a),(b),sizeof((a)))#define CPY(a,b) memcpy ((a), (b), sizeof((a)))#pragma comment(linker, "/STACK:102400000,102400000")#define ul u<<1#define ur (u<<1)|1using namespace std;typedef long long ll;int dp[Mn][Mn];int vis[30];int main() {    int t;    string s;    scanf("%d",&t);    while(t--) {        int k;        scanf("%d",&k);        cin>>s;        CLR(dp,0x3f);        int block=s.size()/k;        for(int i=0;i<block;i++) {            CLR(vis,0);            int cnt=0;            for(int j=i*k;j<(i+1)*k;j++) vis[s[j]-'a']=1;            for(int j=0;j<26;j++) if(vis[j]) cnt++;            if(!i) for(int j=0;j<k;j++) dp[i][j]=cnt;            else for(int j=0;j<k;j++) {                    for(int p=0;p<k;p++) {                        if(vis[s[(i-1)*k+p]-'a']&&(s[i*k+j]!=s[(i-1)*k+p]||cnt==1))                            dp[i][j]=min(dp[i][j],dp[i-1][p]+cnt-1);                        else dp[i][j]=min(dp[i][j],dp[i-1][p]+cnt);                }            }        }        int ans=INF;        for(int i=0;i<k;i++) ans=min(dp[block-1][i],ans);        cout<<ans<<endl;    }    return 0;}


0 0
原创粉丝点击