极大极小搜索+alpha_beta剪枝)

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


你可能感兴趣的:(极大极小搜索+alpha_beta剪枝))