http://poj.org/problem?id=1085
状态dp搜索
#include <cstdio> #include <cstring> #include <algorithm> #include <vector> using namespace std; int dps[1<<12][2]; int mark[18]; vector<int>vec[18]; bool vis[18]; int cnt; int tri[9][3]={ 1,2,3, 4,5,6, 7,8,9, 10,11,12, 13,14,15, 16,17,18, 3,5,7, 6,11,13, 9,14,16 }; int mp[10][10]={ 0,0,1, 0, 0, 0, 0, 0, 0, 0, 0,0,2, 3, 4, 0, 0, 0, 0, 0, 1,2,0, 0, 6, 7, 0, 0, 0, 0, 0,3,0, 0, 5, 0, 9,10, 0, 0, 0,4,6, 5, 0, 8, 0,12,13, 0, 0,0,7, 0, 8, 0, 0, 0,15,16, 0,0,0, 9, 0, 0, 0,11, 0, 0, 0,0,0,10,12, 0,11, 0,14, 0, 0,0,0, 0,13,15, 0,14, 0,17, 0,0,0, 0, 0,16, 0, 0,17, 0 }; int check(int x){ int cou=0; for(int i=0;i<vec[x].size();i++){ if(vis[tri[vec[x][i]][0]] && vis[tri[vec[x][i]][1]] && vis[tri[vec[x][i]][2]]) cou++; } return cou; } int dfs(int sta,int who){ if(dps[sta][who]!=-10000) return dps[sta][who]; if(sta==(1<<cnt)-1) return 0; if(who){ int newbeta=10000; for(int i=0;i<cnt;i++){ if(!(sta&(1<<i))){ vis[mark[i]]=1; int tmp=check(mark[i]); if(tmp) newbeta=min(newbeta,-tmp+dfs(sta|(1<<i),who)); else newbeta=min(newbeta,-tmp+dfs(sta|(1<<i),!who)); vis[mark[i]]=0; } } dps[sta][who]=newbeta; return newbeta; } else{ int newalpha=-10000; for(int i=0;i<cnt;i++){ if(!(sta&(1<<i))){ vis[mark[i]]=1; int tmp=check(mark[i]); if(tmp) newalpha=max(newalpha,tmp+dfs(sta|(1<<i),who)); else newalpha=max(newalpha,tmp+dfs(sta|(1<<i),!who)); vis[mark[i]]=0; } } dps[sta][who]=newalpha; return newalpha; } } void init(){ for(int i=0;i<9;i++) for(int j=0;j<3;j++) tri[i][j]--; for(int i=0;i<9;i++) for(int j=0;j<3;j++) vec[tri[i][j]].push_back(i); } int main(){ init(); int T; scanf("%d",&T); for(int t=0;t<T;t++){ int n; scanf("%d",&n); memset(vis,0,sizeof(vis)); memset(mark,0,sizeof(mark)); int turn=0,x=0,y=0; for(int i=0;i<n;i++){ int u,v; scanf("%d %d",&u,&v); u--,v--; vis[mp[u][v]]=1; int tmp=check(mp[u][v]); if(turn) y+=tmp; else x+=tmp; if(!tmp) turn=!turn; } cnt=0; for(int i=0;i<18;i++) if(!vis[i]) mark[cnt++]=i; for(int i=0;i<(1<<12);i++) dps[i][0]=dps[i][1]=-10000; int tmp=dfs(0,turn); //我在这逗逼一下午,当n为18时dp[0][turn]=-10000; if(tmp+x-y>=0) printf("Game %d: A wins.\n",t+1); else printf("Game %d: B wins.\n",t+1); } return 0; }
38界ACM杭州站I题 HDU 4778
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; int g,b,s; int bag[25][10]; int dps[1<<21][2]; int sum[1<<21]; int dfs(int sta,int last,int who,int alpha,int beta){ int tmp=0,cha=0; tmp=sum[sta]-sum[last]; if(who) cha-=tmp;else cha+=tmp; if(!tmp) who=!who; if(dps[sta][who]!=-10000) return cha+dps[sta][who]; if(who){ if(sta==(1<<b)-1) return cha; int newbeta=10000; bool flag=1; for(int i=0;i<b;i++) if(!(sta&(1<<i))){ newbeta=min(newbeta,dfs(sta|(1<<i),sta,who,-10000,newbeta)); if(newbeta<=alpha){ flag=0;break; } } if(flag)dps[sta][who]=newbeta; return newbeta+cha; } else{ if(sta==(1<<b)-1) return cha; int newalpha=-10000; bool flag=1; for(int i=0;i<b;i++) if(!(sta&(1<<i))){ newalpha=max(newalpha,dfs(sta|(1<<i),sta,who,newalpha,10000)); if(beta<=newalpha){ flag=0;break; } } if(flag)dps[sta][who]=newalpha; return newalpha+cha; } } int main(){ while(scanf("%d %d %d",&g,&b,&s)){ if(g==0 && b==0 && s==0) break; memset(bag,0,sizeof(bag)); for(int i=0;i<b;i++){ int n; scanf("%d",&n); for(int j=0;j<n;j++){ int tmp; scanf("%d",&tmp); tmp--; bag[i][tmp]++; } } int tmp[10]; for(int i=0;i<(1<<b);i++){ for(int j=0;j<g;j++) tmp[j]=0; sum[i]=0; for(int j=0;j<b;j++) if(i&(1<<j)){ for(int k=0;k<g;k++) tmp[k]+=bag[j][k]; } for(int k=0;k<g;k++) sum[i]+=tmp[k]/s; } for(int i=0;i<(1<<b);i++) dps[i][0]=dps[i][1]=-10000; dfs(0,0,1,-10000,10000); printf("%d\n",dps[0][0]); } return 0; }