程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> BZOJ 1443 JSOI2009 游戲Game 二分圖博弈

BZOJ 1443 JSOI2009 游戲Game 二分圖博弈

編輯:C++入門知識

BZOJ 1443 JSOI2009 游戲Game 二分圖博弈


題目大意:給定一個矩陣,一些位置有障礙,先手放置在某個位置,後手移動,先手再移動,一個格子只能經過一次,問是否先手必勝

二分圖博弈= = 將矩陣建成二分圖,考慮二分圖博弈的模型:

給定一個二分圖,每個點只能走一次,先手選定位置後手走,問是否先手必勝

那麼對於任意一個點,如果存在一個最大匹配中這個點沒有被匹配,那麼先手從這個點開始存在必勝策略

先手放置後,後手無論走到哪個點,先手一定能沿著匹配邊走回去

如果不存在匹配邊,說明找到了一條增廣路,與最大匹配的前提相悖,故一定存在匹配邊

當二分圖存在完備匹配時先手必敗。

這個題還讓我們求出先手選擇哪些點可以必勝

那麼我們做兩次最大匹配,每次只考慮左邊的點哪些可以必勝

枚舉每個未匹配的點,沿著出邊->匹配邊->出邊->匹配邊的順序開始深搜,深搜到的所有左側的點就是左側的可選點集。

時間復雜度O(n^2) 雖然數據范圍是10000但是匈牙利算法的常數很小 親測可過

坑比樣例- - 別忘了輸出WIN。。。

#include 
#include 
#include 
#include 
using namespace std;
struct abcd{
	int to,next;
}table[20200];
int head[5050],tot;
int m,n,n1,n2;
char map[110][110];
int pos[110][110];
bool ans[2][5050];
void Add(int x,int y)
{
	table[++tot].to=y;
	table[tot].next=head[x];
	head[x]=tot;
}
namespace Bipartite_Graph_Maximum_Match{
	int result[5050];
	bool state[5050],lonely[5050];
	bool Hungary(int x)
	{
		int i;
		for(i=head[x];i;i=table[i].next)
		{
			if(state[table[i].to])
				continue;
			state[table[i].to]=1;
			if( !result[table[i].to] || Hungary(result[table[i].to]) )
			{
				result[table[i].to]=x;
				return true;
			}
		}
		return false;
	}
	void DFS(int x,bool ans[])
	{
		int i;
		ans[x]=true;
		for(i=head[x];i;i=table[i].next)
			if(!ans[result[table[i].to]])
				DFS(result[table[i].to],ans);
	}
}
using namespace Bipartite_Graph_Maximum_Match;
void Initialize()
{
	memset(head,0,sizeof head);
	tot=0;
	memset(result,0,sizeof result);
	memset(lonely,0,sizeof lonely);
}
int main()
{

	static const int dx[]={0,0,1,-1};
	static const int dy[]={1,-1,0,0};
	int i,j,k;
	cin>>m>>n;
	for(i=1;i<=m;i++)
	{
		scanf("%s",map[i]+1);
		for(j=1;j<=n;j++)
			if(map[i][j]=='.')
				pos[i][j]=++(i+j&1?n1:n2);
	}

	for(i=1;i<=m;i++)
		for(j=1;j<=n;j++)
			if( i+j&1 && map[i][j]=='.' )
				for(k=0;k<4;k++)
				{
					int x=i+dx[k];
					int y=j+dy[k];
					if(x<=0||y<=0||x>m||y>n||map[x][y]=='#')
						continue;
					Add(pos[i][j],pos[x][y]);
				}
	int matches=0;
	for(i=1;i<=n1;i++)
	{
		memset(state,0,sizeof state);
		if( Hungary(i) )
			matches++;
		else
			lonely[i]=true;
	}
	if( matches==n1 && matches==n2 )
		return cout<<"LOSE"<m||y>n||map[x][y]=='#')
						continue;
					Add(pos[i][j],pos[x][y]);
				}
	for(i=1;i<=n2;i++)
	{
		memset(state,0,sizeof state);
		if( !Hungary(i) )
			lonely[i]=1;
	}
	for(i=1;i<=n2;i++)
		if(lonely[i])
			DFS(i,ans[0]);

	cout<<"WIN"<

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved