pku1085 Triangle War 完全极大极小搜索+状压DP

黑书入门题,我们记录下每一个状态,状态为每条边是否用上,然后记忆化搜索所有状态

WA了一次,因为搜索的时候给状态的值的时候写成了一共的三角形数量而不是双方的最大差值

时间复杂度为2^18*8*17,而且每组数据都不需要额外更新,话说这样写时间复杂度是常数级别的诶2333333333

Problem: 1085		User: BPM136
Memory: 2724K		Time: 188MS
Language: G++		Result: Accepted

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#include<bitset>
#define LL long long
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define down(i,a,b) for(int i=a;i>=b;i--)
using namespace std;
inline LL read()
{
	LL d=0,f=1;char s=getchar();
	while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
	while(s>='0'&&s<='9'){d=d*10+s-'0';s=getchar();}
	return d*f;
}
#define N 18
#define MIN -10
int tri[9]={7,52,152,352,3200,12544,34304,71680,155648};
int m=(1<<18)-1;
int map[11][11]={0};
int pri[4][2]={1,0,0,1,-1,0,0,-1};
int f[(1<<19)+5];
int n;

void getmap()
{
	memset(map,0,sizeof(map));
	map[1][2]=1;map[1][3]=2;
	map[2][3]=3;map[2][4]=4;map[2][5]=5;
	map[3][5]=6;map[3][6]=7;
	map[4][5]=8;map[4][7]=10;map[4][8]=11;
	map[5][6]=9;map[5][8]=12;map[5][9]=13;
	map[6][9]=14;map[6][10]=15;
	map[7][8]=16;
	map[8][9]=17;
	map[9][10]=18;
	fo(i,1,9)
	fo(j,i+1,10)
	if(map[i][j])
	map[j][i]=map[i][j];
}

int getvalue(int old,int now)
{
	int ret=0;
	fo(i,0,8)
	if((old&tri[i])!=tri[i]&&(now&tri[i])==tri[i])
		ret++;
	return ret;
}

int calc(int now)
{
	if(f[now]!=MIN)return f[now];
	int cnt=getvalue(0,now),ma=MIN;
	bitset<20>t;t=now;
	fo(i,0,17)
	if(t[i]==0)
	{
		t[i]=1;
		int ne=t.to_ulong();
		int val=getvalue(now,ne);
		if(val>0)val+=calc(ne);
		else val+=-1*calc(ne);
		ma=max(ma,val);
		t[i]=0;
	}
	return f[now]=ma;
}

void solve(int ch)
{
	n=read();
	int player=1,cnt=0;
	bitset<20>t;t.reset();
	fo(i,1,n)
	{
		int x=read(),y=read();
		int k=0;
		if(map[x][y])
		{
//			cout<<"B:"<<map[x][y]<<endl;
			unsigned long old=t.to_ulong();
			t[map[x][y]-1]=1;
			unsigned long now=t.to_ulong();
			k=getvalue(old,now);
		}
		if(k)cnt+=player*k;
		else player*=-1;
	}
	unsigned long now=t.to_ulong();
//	cout<<now<<endl;
	cnt+=player*calc(now);
	if(cnt>0)printf("Game %d: A wins.\n",ch);
	else printf("Game %d: B wins.\n",ch);
}

int main()
{
	getmap();
	fill(f,f+(1<<19),-10);
	f[m]=0;
//	cout<<getvalue(7,m)<<endl;
	int ttttt=read();
	fo(i,1,ttttt)solve(i);
	return 0;
}


你可能感兴趣的:(状压dp,完全极大极小搜索)