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


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值