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;
}