首页 > 代码库 > sdut2879 枚举起点DP

sdut2879 枚举起点DP

这个题和乌龟棋之类的DP差不多要学会缩减状态

就是,,我们只需枚举当前这个人是谁,选什么颜色,A用了多少,B用了多少

C用了多少我们就不用枚举了,知道选了多少人,A,B用了多少,你还不知C用了多少么,因为总共只有这三种颜色

然后结尾不能与开头相同。。我郁闷了好久。。因为并不能直接知道开头是什么状态。。

那么一种想法就是枚举开头的三种情况(如果有的话),做三次DP,直接调用全局变量就能知道开始时是什么颜色

我写了个记忆化搜索,TLE了,改成DP应该能过

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
char s[100];
int col[4],cf;//first color 
int dp[55][3][55][55];
int dfs(int x,int cx,int c0,int c1){
    // printf("pos:%d col:%d c0:%d c1:%d\n",x,cx,c0,c1);
    if(dp[x][cx][c0][c1]!=-1) return dp[x][cx][c0][c1];
    if(x==col[3]){
        //这里用枚举
        if(cx!=cf) return dp[x][cx][c0][c1]=1;
        return dp[x][cx][c0][c1]=0;
    }
    int ans=0;
    for(int i=0;i<3;++i){
        if(i!=cx) {
            if(i==0&&col[0]-c0<=0) continue;
            if(i==1&&col[1]-c1<=0) continue;
            // if(i==2&&col[2]+c0+c1>=col[3]) continue;
            if(i==2&&col[2]-(x-c0-c1)<=0) continue;
            if(i==0){
                ans+=dfs(x+1,i,c0+1,c1);
            }
            else if(i==1){
                ans+=dfs(x+1,i,c0,c1+1);
            }
            else{
                ans+=dfs(x+1,i,c0,c1);
            }
        }
    }
    return ans;
}
void solve(){
    int i,j,k,p;

    for(i=col[3];i>=1;--i){
        for(j=0;j<3;++j){
            for(k=0;k<)
        }
    }
}
int main(){
    //3^12 约等于 50000+
    int T;scanf("%d",&T);
    while(T--){
        scanf("%s",s);
        int len=strlen(s),i;
        memset(col,0,sizeof(col));
        memset(dp,-1,sizeof(dp));
        for(i=0;i<len;++i){
            col[s[i]-A]++;
        }
        col[3]=len;
        int res=0;
        for(i=0;i<3;++i){
            cf=i;
            if(col[i]>0)
            
        }
        printf("%d\n",res);
    }
    return 0;
}

 

sdut2879 枚举起点DP