这个题和乌龟棋之类的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; }
时间: 2024-10-15 01:38:59