hdu-4753-Fishhead’s Little Game-记忆化搜索
网赛的一道题目,当时没做出来。
由题意可知,最多只有12条边未知。
所以最多只有(1<<12)种状态。
所以记忆化搜索这种状态下,枚举添加任意一条边之后的状态的最优值。
#include<stdio.h> #include<string.h> #include<stdlib.h> #include<algorithm> #include<iostream> using namespace std; int dp[10001]; int visit[10001]; int vis[25]; int oth[25]; int ts; int num(int vist[]) { int i; int sum=0; for(i=1;i<=9;i++) { if(vist[i]&&vist[i+3]&&vist[i+12+(i-1)/3]&&vist[i+13+(i-1)/3])sum++; } return sum; } int dos(int x) { int sum=0,i; int vist[26]; for(i=0;i<=24;i++)vist[i]=0; for(i=1;i<=ts;i++) { if(x&(1<<(i-1))) { vist[oth[i-1]]=1; } } for(i=1;i<=24;i++) { if(vis[i])vist[i]=1; } sum=num(vist); return sum; } int dfs(int x) { if(visit[x]!=-1)return visit[x]; int ans=0; for(int i=1;i<=ts;i++) { if(!(x&(1<<(i-1)))) { int y; y=x+(1<<(i-1)); int ss; ss=dfs(y); ans=max(9-dp[x]-ss,ans); } } visit[x]=ans; return ans; } int main() { int T,i,n,a,b; int cas; int anum,bnum,s; cas=0; scanf("%d",&T); while(T--) { cas++; anum=bnum=0; s=0; scanf("%d",&n); memset(vis,0,sizeof(vis)); memset(visit,-1,sizeof(visit)); for(i=0;i<n;i++) { scanf("%d%d",&a,&b); if(a>b)swap(a,b); if(b-a==4)ts=12+a; else ts=a-a/4; vis[ts]=1; if(i%2==0) { anum+=num(vis)-s; } else bnum+=num(vis)-s; s=num(vis); } ts=0; for(i=1;i<=24;i++)if(vis[i]==0)oth[ts++]=i; for(i=0;i<(1<<ts);i++)dp[i]=dos(i); int have; have=9-s; int fs; fs=dfs(0); //printf("%d %d %d %d\n",anum,bnum,have,fs); printf("Case #%d: ",cas); if(n%2==0) { if(anum+fs>bnum+have-fs)cout<<"Tom200"<<endl; else cout<<"Jerry404"<<endl; } else { if(anum+have-fs>bnum+fs)cout<<"Tom200"<<endl; else cout<<"Jerry404"<<endl; } } return 0; }