T180751 组队赛

我们明显可以发现这是一个状压dp
由于两边都聪明,所以每一次出人肯定会出可以打下别人的。
由此我们可以得到\(f(s1,s2,i)\)表示甲乙的状态为\(s1\),\(s2\),擂主为\(i\)时甲/乙赢。
这就是一个博弈的题目。
由于双方都非常聪明,在确定擂主的情况下,哪一方出人就确定了,而且剩下的人也是确定的,这种情况下胜负也是确定的,也就是说这样定义就可以确定下一个确定的状态了。
具体实现使用递归/dfs会好做一点
注意空间很可能会炸掉。
这是一道罕见的比标程还短的题,处理很精妙,具体看代码

#include<bits/stdc++.h>
using namespace std;
int n;
bool used[4133][4133][21],f[4133][4133][21];
char s[1001],c[1001][1001];
bool dfs(int s1,int s2,int t)//t<0乙->t>0甲 
{
	if(used[s1][s2][t+10])return f[s1][s2][t+10];
	used[s1][s2][t+10]=1;
	bool b;
	if(t>0)b=1;
	else b=0;
	if(t<0)//甲 
	for(int i=1;i<=n;i++)
	{
		if((((1<<(i-1))&s1))||c[i][abs(t)]=='0')continue;
		b=max(b,dfs(s1|(1<<(i-1)),s2,i));
	}
	else
	for(int i=1;i<=n;i++)
	{
		if((((1<<(i-1))&s2))||c[abs(t)][i]=='1')continue;
		b=min(b,dfs(s1,s2|(1<<(i-1)),-i));
	}
	f[s1][s2][t+10]=b;
	return f[s1][s2][t+10];
}
int main()
{
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		cin>>(s+1);
		for(int j=1;j<=n;j++)
		c[i][j]=s[j];
	}
	bool ans=0;
	for(int i=1;i<=n;i++)
	ans=max(ans,dfs(1<<(i-1),0,i));
	cout<<ans;
}
posted @ 2021-07-24 16:17  lei_yu  阅读(22)  评论(0编辑  收藏  举报