UVa:11552 - Fewest Flops

动态规划。

dp【i】【j】【k】表示前i组中,第i组以j开头以k结束时的最小组数。

这样取a【j】=min{dp【i-1】【k】【j】},该组内块数为val

则dp【i】【k】【q】=if k==j min{dp【i】【k】【q】,a【j】+val-1}

                                        else  min{dp【i】【k】【q】,a【j】+val}

动态规划算法可能有当前状态之前的多个状态转移而来,而这个题只由前一个状态转移而来,因此可以使用滚动数组优化空间。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <vector>
#include <queue>
#include <map>
#include <algorithm>
#define ll long long
#define INF 2139062143
#define inf -2139062144
#define MOD 20071027
#define MAXN 1005
using namespace std;
int dp[30][30];
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int d;
        char str[MAXN];
        scanf("%d%s",&d,str);
        int L=strlen(str),n=L/d;
        memset(dp,0x7f,sizeof(dp));
        for(int i=0; i<n; ++i)
        {
            bool vis[30]= {0};
            int st=i*d,ed=(i+1)*d;
            for(int j=st; j<ed; ++j)
                vis[str[j]-'a']=true;
            int val=0;
            for(int j=0; j<26; ++j)
                if(vis[j]) val++;
            if(i==0)
            {
                if(val==1)
                    dp[str[0]-'a'][str[0]-'a']=1;
                else
                {
                    for(int j=0; j<26; ++j)
                        for(int k=0; k<26; ++k)
                            if(vis[j]&&vis[k]&&j!=k) dp[j][k]=val;
                }
            }
            else
            {
                int a[MAXN];
                memset(a,0x7f,sizeof(a));
                for(int j=0; j<26; ++j)
                    for(int k=0; k<26; ++k)
                        a[k]=min(a[k],dp[j][k]);
                memset(dp,0x7f,sizeof(dp));
                if(val==1)
                {
                    int t=str[st]-'a';
                    for(int j=0; j<26; ++j)
                        if(a[j]!=INF)
                        {
                            if(t==j) dp[t][t]=min(dp[t][t],a[j]);
                            else dp[t][t]=min(dp[t][t],a[j]+1);
                        }
                }
                else
                {
                    for(int j=0; j<26; ++j)
                        for(int k=0; k<26; ++k)
                            for(int q=0; q<26; ++q)
                                if(vis[k]&&vis[q]&&k!=q&&a[j]!=INF)
                                {
                                    if(k==j) dp[k][q]=min(dp[k][q],a[j]+val-1);
                                    else dp[k][q]=min(dp[k][q],a[j]+val);
                                }
                }
            }
        }
        int ans=INF;
        for(int i=0; i<26; ++i)
            for(int j=0; j<26; ++j)
                ans=min(dp[i][j],ans);
        printf("%d\n",ans);
    }
    return 0;
}


 

你可能感兴趣的:(动态规划)