Codeforces Round #648 (Div. 2)——ABCD題解

A. Matrix Game

傳送門A. Matrix Game

題目:

在這裏插入圖片描述

測試樣例:

輸入樣例:
4
2 2
0 0
0 0
2 2
0 0
0 1
2 3
1 0 1
1 1 0
3 3
1 0 0
0 0 0
1 0 0

輸出樣例:
Vivek
Ashish
Vivek
Ashish

Note
For the first case: One possible scenario could be: Ashish claims cell (1,1), Vivek then claims cell (2,2). Ashish can neither claim cell (1,2), nor cell (2,1) as cells (1,1) and (2,2) are already claimed. Thus Ashish loses. It can be shown that no matter what Ashish plays in this case, Vivek will win.
For the second case: Ashish claims cell (1,1), the only cell that can be claimed in the first move. After that Vivek has no moves left.
For the third case: Ashish cannot make a move, so Vivek wins.
For the fourth case: If Ashish claims cell (2,3), Vivek will have no moves left.

題目大意:

  有n*m的單元格,其中只包含0和1,1單元格的同行同列都是不可操作的。現在Ashish和Vivek在玩遊戲,在可操作的地方將0替換成1。Ashish先開始遊戲,當某人無法進行操作時,對方獲勝。

思路:

  先標記給定單元格中的無法操作的行和列,然後對可操作的單元格進行操作,每次操作後標記相應的行和列不可操作。統計進行的操作次數,奇數次則Ashish贏,否則Vivek獲勝(因爲Ashish先手操作)。

AC代碼:

#include<iostream>
#include<string>
#include<cstdio>
#include<cstring>
using namespace std;
typedef long long ll;
int a[55][55];
int vis1[55],vis2[55];
int main()
{
	int T;
	cin>>T;
	while(T--)
	{
		//多組樣例
		memset(vis1,0,sizeof(vis1));
		memset(vis2,0,sizeof(vis2));
		int n,m;
		cin>>n>>m;
		for(int i=1;i<=n;i++)
		{
			for(int j=1;j<=m;j++)
			{
				cin>>a[i][j];
				//如果爲 1,標記行和列不可操作
				if(a[i][j]==1)
				{
					vis1[i]=1;
					vis2[j]=1;
				}
			}
		}
		int cnt=0;
		for(int i=1;i<=n;i++)
		{
			if(vis1[i]!=1)//行可以操作
			{
				for(int j=1;j<=m;j++)
				{
					if(vis2[j]!=1)//列可以操作
					{
						cnt++;
						vis1[i]=1;//標記行不可操作
						vis2[j]=1;//標記列不可操作
						break;
					}
				}
			}
		}
		if(cnt&1)
			cout<<"Ashish"<<endl;
		else
			cout<<"Vivek"<<endl;	
	}
	return 0;
}

B. Trouble Sort

傳送門:B. Trouble Sort

題目:

在這裏插入圖片描述

測試樣例:

輸入樣例:
5
4
10 20 20 30
0 1 0 1
3
3 1 2
0 1 1
4
2 2 4 8
1 1 1 1
3
5 15 4
0 0 0
4
20 10 100 50
1 0 0 1

輸出樣例:
Yes
Yes
Yes
No
Yes

Note
For the first case: The elements are already in sorted order.
For the second case: Ashish may first swap elements at positions 1 and 2, then swap elements at positions 2 and 3.
For the third case: The elements are already in sorted order.
For the fourth case: No swap operations may be performed as there is no pair of elements i and j such that bi≠bj. The elements cannot be sorted.
For the fifth case: Ashish may swap elements at positions 3 and 4, then elements at positions 1 and 2.

題目大意:

  T組測試樣例,每組測試樣例N個元素,每個元素有值和類型兩個屬性(第一行是值,第二行是類型)。可以選擇不同類型的元素進行交換位置,問最終能否得到單調不降的值序列。

思路:

  如果原來的值序列本身不是有序的且所有的元素的類型相同,則不能得到單調不降的值序列,因爲沒有另一種類型的元素,無法交換。
  只要有元素的類型不同,就一定可以通過交換得到單調不降的值序列。

AC代碼:

#include<iostream>
#include<string>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
int value[505],type[505],temp[505];
int main()
{
	int T;
	cin>>T;
	while(T--)
	{
		int n;
		cin>>n;
		for(int i=0;i<n;i++)
		{
			cin>>value[i];
			temp[i]=value[i];
		}
		//兩種類型個數
		int cnt1=0,cnt2=0;
		for(int i=0;i<n;i++)
		{
			cin>>type[i];
			if(type[i]==1)
				cnt1++;
			else
				cnt2++;
		}
		sort(temp,temp+n);
		int flag=1;
		//判斷原值序列是否單調不降
		for(int i=0;i<n;i++)
		{
			if(value[i]!=temp[i])
			{
				flag=0;
				break;
			}
		}
		//如果原值序列不是單調不降且所有元素只有一種類型
		if(!flag&&((!cnt1&&cnt2)||(!cnt2&&cnt1)))
			cout<<"No"<<"\n";
		else
			cout<<"Yes"<<"\n";	
	}
	return 0;
}

C. Rotation Matching

傳送門:C. Rotation Matching

題目:

在這裏插入圖片描述

測試樣例:

輸入樣例1:
5
1 2 3 4 5
2 3 4 5 1
輸出樣例15

輸入樣例25
5 4 3 2 1
1 2 3 4 5
輸出樣例21

輸入樣例34
1 3 2 4
4 2 3 1
輸出樣例32

Note
For the first case: b can be shifted to the right by k=1. The resulting permutations will be {1,2,3,4,5} and {1,2,3,4,5}.
For the second case: The operation is not required. For all possible rotations of a and b, the number of matching pairs won’t exceed 1.
For the third case: b can be shifted to the left by k=1. The resulting permutations will be {1,3,2,4} and {2,3,1,4}. Positions 2 and 4 have matching pairs of elements. For all possible rotations of a and b, the number of matching pairs won’t exceed 2.

題目大意:

  給定兩組數,每組N個。可以將一組數整體向左或者向右循環移動K個單位。問:移動後相同位置相同的最多有多少個。

思路:

  題中說了每個數字都不重複。則可以計算兩組數中相同數的相對位置差並統計,最後找同位置差個數最多的即可。即如果有K個數位置差都是m,則同時移動m個單位就會有k個數能夠相互對應,找最大的cnt[m]即可。

AC代碼:

#include<iostream>
#include<cstring>
#define IOS ios::sync_with_stdio(false);
using namespace std;
const int MAXN=2e5+5;
int a[MAXN],b[MAXN],cnt[MAXN];
int main()
{
	IOS
	int n,k;
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		cin>>k;
		//第一組數,數字 k 在 i 號位置
		a[k]=i;
	}
	for(int i=1;i<=n;i++)
	{
		cin>>k;
		//第二組數,數字 k 在 i 號位置
		b[k]=i;
	}	
	for(int i=1;i<=n;i++)
	{
		int temp=(n+a[i]-b[i])%n;//相對位置差
		cnt[temp]++;//統計 相對位置差爲 temp 的個數
	}		
	int ans=0;
	for(int i=0;i<=n;i++)
		ans=max(ans,cnt[i]);
	cout<<ans<<"\n";
	return 0;
}

D. Solve The Maze

傳送門:D. Solve The Maze

題目:

在這裏插入圖片描述

測試樣例:

輸入樣例:
6
1 1
.
1 2
G.
2 2
#B
G.
2 3
G.#
B#.
3 3
#B.
#..
GG.
2 2
#B
B.

輸出樣例:
Yes
Yes
No
No
Yes
Yes

Note
For the first and second test cases, all conditions are already satisfied.
For the third test case, there is only one empty cell (2,2), and if it is replaced with a wall then the good person at (1,2) will not be able to escape.
For the fourth test case, the good person at (1,1) cannot escape.
For the fifth test case, Vivek can block the cells (2,3) and (2,2).
For the last test case, Vivek can block the destination cell (2,2).

題目大意:

  現在有n*m的迷宮,(n,m)是出口,在迷宮裏 ’ . ’ 表示空,’ # ‘表示牆,’ G ‘表示好人,’ B '表示壞人。好人和壞人可以走上下左右四個方向,有牆的地方不能通過,可以將空的地方用牆堵起來阻礙通過。
  問:能否將某些空的地方堵上牆,使得所有的壞人無法逃出迷宮,而所有的好人都能逃出迷宮。

思路:

  如果壞人四周某個方向有好人就一定不行,因爲壞人可以跟着好人出去。此時爲"No"
  如果壞人四周有空地地方,就將空的地方換成牆來阻礙壞人通過(此時並不會因爲都換成了牆而阻礙到好人,因爲如果會阻礙到好人通過,則壞人也可以跟着好人通過)。
  當壞人四周的空都換成牆後(已經保證所有壞人出不去了):
    1、如果出口也被堵住了,且有好人在迷宮中,則好人也無法出去了。此時爲"No"
    2、如果出口沒被堵住,就判斷能走出迷宮的好人和好人總數是否相等。相等即所有好人都可以出去爲"Yes",否則是"No"。
  當搜索能走出迷宮好人數目時,因爲所有好人有共同的出口,所以可以從出口開始搜索,加快搜索速度。

AC代碼1(DFS):

#include<iostream>
#include<cstring>
#include<queue>
using namespace std;
int dir[4][2]={1,0,-1,0,0,1,0,-1};
char g[55][55];
bool vis[55][55];
int n,m;
int cnt=0,ans=0;
bool check(int x,int y)
{
	return (x>0&&y>0&&x<=n&&y<=m);
}
//需要剪枝,走過的路不再走,不恢復標記
void dfs(int x,int y)
{
	vis[x][y]=1;
	if(g[x][y]=='G')
		ans++;
	for(int i=0;i<4;i++)
	{
		int dx=x+dir[i][0];
		int dy=y+dir[i][1];
		if(check(dx,dy)&&!vis[dx][dy]&&g[dx][dy]!='#')
			dfs(dx,dy);
	}
}
void solve()
{
	ans=0;
	cnt=0;
	memset(vis,0,sizeof(vis));
	cin>>n>>m;
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=m;j++)
		{
			cin>>g[i][j];
			if(g[i][j]=='G')//統計好人個數
				cnt++;
		}
	}
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=m;j++)
		{
			if(g[i][j]=='B')
			{
				for(int k=0;k<4;k++)
				{
					int dx=i+dir[k][0];
					int dy=j+dir[k][1];
					if(check(dx,dy))//四周
					{
						if(g[dx][dy]=='.')//堵牆
							g[dx][dy]='#';
						if(g[dx][dy]=='G')//壞人可以跟着好人走出去
						{
							cout<<"No\n";
							return ;
						}	
					}
				}
			}
		}
	}
	if(g[n][m]=='#')//出口被堵住了
	{
		if(cnt==0)//沒有好人
			cout<<"Yes\n";
		else
			cout<<"No\n";
		return ;
	}
	dfs(n,m);//搜索能走出迷宮的好人數
	if(ans==cnt)
		cout<<"Yes"<<"\n";
	else
		cout<<"No"<<"\n";
}
int main()
{
	int T;
	cin>>T;
	while(T--)
		solve();	
	return 0;
}

AC代碼2(BFS):

#include<iostream>
#include<cstring>
#include<queue>
using namespace std;
int dir[4][2]={1,0,-1,0,0,1,0,-1};
char g[55][55];
bool vis[55][55];
int n,m;
int cnt=0,ans=0;
bool check(int x,int y)
{
	return (x>0&&y>0&&x<=n&&y<=m);
}
void bfs()
{
	typedef pair<int,int> P;
	queue<P> q;
	vis[n][m]=1;
	q.push(P(n,m));
	while(!q.empty())
	{
		P temp=q.front();
		q.pop();
		int x=temp.first;
		int y=temp.second;
		for(int i=0;i<4;i++)
		{
			int dx=x+dir[i][0];
			int dy=y+dir[i][1];
			if(check(dx,dy)&&g[dx][dy]!='#'&&!vis[dx][dy])
			{
				if(g[dx][dy]=='G')
					ans++;
				q.push(P(dx,dy));
				vis[dx][dy]=1;	
			}
		}	
	}
}
void solve()
{
	ans=0;
	cnt=0;
	memset(vis,0,sizeof(vis));
	cin>>n>>m;
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=m;j++)
		{
			cin>>g[i][j];
			if(g[i][j]=='G')//統計好人個數
				cnt++;
		}
	}
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=m;j++)
		{
			if(g[i][j]=='B')
			{
				for(int k=0;k<4;k++)
				{
					int dx=i+dir[k][0];
					int dy=j+dir[k][1];
					if(check(dx,dy))//四周
					{
						if(g[dx][dy]=='.')//堵牆
							g[dx][dy]='#';
						if(g[dx][dy]=='G')//壞人可以跟着好人走出去
						{
							cout<<"No\n";
							return ;
						}	
					}
				}
			}
		}
	}
	if(g[n][m]=='#')//出口被堵住了
	{
		if(cnt==0)//沒有好人
			cout<<"Yes\n";
		else
			cout<<"No\n";
		return ;
	}
	bfs();//搜索能走出迷宮的好人數
	if(ans==cnt)
		cout<<"Yes"<<"\n";
	else
		cout<<"No"<<"\n";
}
int main()
{
	int T;
	cin>>T;
	while(T--)
		solve();	
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章