test20200415 game and NOI2011 Bunny and Egg game

test20200415 game

Alice and Bob are playing a game, giving a \ (n \ times m \) board with some points on it as obstacles. At the beginning of the game, Alice selects any grid on the board that is not an obstacle, and puts one Put the pieces in it, then Bob first moves, and the two people take turns to operate the pieces. Each operation must move the pieces from the current position to an adjacent barrier-free and unpassed grid (that is, each grid is not allowed to pass twice). The operator loses. If both of them operate according to the optimal strategy, I would like to ask which grid Alice puts the pieces on at the beginning.

For 100% data: \ (1 \ leq n, m \ leq 100 \) .

answer

First of all, this is a bipartite graph. We consider each Unicom block separately.

  • If a point is not necessarily in the maximum match, then this point Alice must win.

    Proof: Choose a maximum match that does not match this point. Bob must walk the non-matching edge for the first time, and then Alice can only walk the non-matching edge as long as she keeps walking the matching edge. If Bob wins, it means finding a way of augmentation, contradiction.

  • If a point must be in the maximum match, then this point Bob will win.

    Proof: Choose any maximum match. As long as Bob keeps walking on the matching edge, Alice can only walk on the non-matching edge. If Alice wins, you can construct a maximum match that is unmatched at this point, contradictory.

Therefore, it is only necessary to judge whether each point is not necessarily in the maximum match. Just look for Zengguang Road in a similar way.

Time complexity \ (O (nm \ sqrt {nm}) \) .

CO int N=101;
char grid[N][N];
int idx[N][N],num;
int pos[N*N][2],col[N*N];
vector<int> to[N*N];
int vis[N*N],tim,mat[N*N];

bool dfs(int x){
	for(int y:to[x])if(vis[y]!=tim){
		vis[y]=tim;
		if(!mat[y] or dfs(mat[y])){
			mat[y]=x;
			return 1;
		}
	}
	return 0;
}

int win[N*N];

void find(int x){
	for(int y:to[x]){
		if(mat[y]!=0 and win[mat[y]]==0)
			win[mat[y]]=1,find(mat[y]);
	}
}

int main(){
	int n=read<int>(),m=read<int>();
	for(int i=1;i<=n;++i) scanf("%s",grid[i]+1);
	function<void(int,int)> link=[&](int u,int v)->void{
		to[u].push_back(v),to[v].push_back(u);
	};
	for(int i=1;i<=n;++i)
		for(int j=1;j<=m;++j)if(grid[i][j]=='.'){
			idx[i][j]=++num;
			pos[num][0]=i,pos[num][1]=j;
			col[num]=(i+j)&1;
			if(i>1 and grid[i-1][j]=='.') link(num,idx[i-1][j]);
			if(j>1 and grid[i][j-1]=='.') link(num,idx[i][j-1]);
		}
	for(int i=1;i<=num;++i)if(!col[i])
		++tim,dfs(i);
	for(int i=1;i<=num;++i)if(col[i])
		if(mat[i]) mat[mat[i]]=i;
	for(int i=1;i<=num;++i)if(!mat[i])
		win[i]=1,find(i);
	int ans=accumulate(win+1,win+num+1,0);
	printf("%d\n",ans);
	for(int i=1;i<=num;++i)if(win[i])
		printf("%d %d\n",pos[i][0],pos[i][1]);
	return 0;
}

NOI2011 Bunny and Egg Game

These days, Bunny and Egg are in love with a new board game.

This game is played on a chessboard in the \ (n \) row \ (m \) column. Before the game started, one of the checkers on the board was empty, and all the other checkers were placed with a chess piece, either black or white.

Each game is always operated by Bunny first, and then the two sides take turns to operate. The specific operations are:

  • Each time Bunny operates, select a white pawn adjacent to the space and move it into the space.

  • Every time the egg works, select a black piece adjacent to the space and move it into the space.

The first person who cannot follow the rules loses the game. For the convenience of description, the operation "Move the pawn in row x and column y into the space" is marked as \ (M (x, y) \) .

For example, the following are examples of three games.

Recently Tutu has always lost the game, and the eggs are particularly arrogant, so Tutu wants to ask her good friend-you-to help her. She brought a game record of the game she lost to the egg, please point out all the places where she "made a mistake" in this game.

note:

  • Two grids are adjacent if and only if they have a common edge.

  • Tutu's operation is "to make mistakes", if and only if, before this operation, Tutu has a winning strategy, and after this operation, Egg has a winning strategy.

For the data of \ (100 \% \) , \ (1 \ leq n \ leq 40 \) , \ (1 \ leq m \ leq 40 \) , \ (1 \ leq k \ leq 1000 \) .

answer

https://www.luogu.com.cn/blog/duyi/solution-p1971

We regard the moving process as the middle space is moving, then the space must move alternately between the black grid and the white grid, which becomes a bipartite graph model:

In a bipartite graph, move a piece from a given starting point u. The two players move in turn and must not pass through repeated points. If one side cannot move, it is a loser.

The conclusion of this model is that the back hand must win (the first hand must lose) if and only if there is a maximum match and does not include the starting point u.

Understand briefly, when there is a set of maximum matches that do not include the starting point u, start with u first, and then take a non-matching edge. At this time, the back hand must go down a matching edge, and then take a non-matching edge first, so Go back and forth until the end, the first move is boundless. At this time the backhand will win. Why does the back hand always find the next matching edge? Because otherwise the path they go out starts with a non-matching edge and ends with a non-matching edge-this is an augmented path! Obviously does not meet the "maximum match" condition.

How to check whether there is a maximum match that does not contain u? We only need to remove u to see if the original image can be expanded. If it can, it means that a new maximum match has been found, that is, there is a maximum match that does not contain u. At this time, the first move will lose, otherwise the first move will win.

Pay attention to the implementation details of this question: after a space is removed, the grid where it was originally should be banned. Because the color of the original grid has changed substantially before and after, the edges are gone.

CO int N=50,M=1e3+10;
int grid[N][N],idx[N][N],num;
vector<int> to[N*N];
int vis[N*N],tim,mat[N*N],ban[N*N];
CO int dx[4]={-1,1,0,0},dy[4]={0,0,-1,1};

bool dfs(int x){
	if(ban[x]) return 0;
	for(int y:to[x]){
		if(vis[y]==tim or ban[y]) continue;
		vis[y]=tim;
		if(!mat[y] or dfs(mat[y])){
			mat[x]=y,mat[y]=x;
			return 1;
		}
	}
	return 0;
}
int main(){
	int n=read<int>(),m=read<int>();
	int bx=0,by=0;
	for(int i=1;i<=n;++i){
		static char str[N];scanf("%s",str+1);
		for(int j=1;j<=m;++j){
			if(str[j]=='O') grid[i][j]=0;
			else if(str[j]=='X') grid[i][j]=1;
			else grid[i][j]=1,bx=i,by=j;
		}
	}
	for(int i=1;i<=n;++i)
		for(int j=1;j<=m;++j) idx[i][j]=++num;
	for(int i=1;i<=n;++i)
		for(int j=1;j<=m;++j)if(grid[i][j]){
			for(int k=0;k<4;++k){
				int x=i+dx[k],y=j+dy[k];
				if(x<1 or x>n or y<1 or y>m) continue;
				if(grid[x][y]) continue;
				to[idx[i][j]].push_back(idx[x][y]);
				to[idx[x][y]].push_back(idx[i][j]);
			}
		}
	for(int i=1;i<=n;++i)
		for(int j=1;j<=m;++j)if(grid[i][j])
			++tim,dfs(idx[i][j]);
	int q=read<int>();
	vector<int> ans;
	for(int i=1;i<=q;++i){
		int win=0;
		int x=idx[bx][by];
		ban[x]=1;
		if(mat[x]){
			int y=mat[x];
			mat[x]=mat[y]=0;
			++tim,win+=!dfs(y);
		}
		read(bx),read(by);
		x=idx[bx][by];
		ban[x]=1;
		if(mat[x]){
			int y=mat[x];
			mat[x]=mat[y]=0;
			++tim,win+=!dfs(y);
		}
		read(bx),read(by);
		if(win==2) ans.push_back(i);
	}
	printf("%zd\n",ans.size());
	for(int x:ans) printf("%d\n",x);
	return 0;
}

Guess you like

Origin www.cnblogs.com/autoint/p/12705824.html