AtCoder Grand Contest 033

A - Darker and Darker

题意:有一个n*m的字符,‘#'代表黑色,’.'代表白色,每次能使得黑色上下左右的白色变黑,求最少操作次数可以将他全部变黑。

思路:以每个黑色点做最短路,再bfs。

#include<bits/stdc++.h>
using namespace std;
char s[1005][1005];
int d[1005][1005];
int x[1000005],y[1000005];
int h,w;
int dx[4]={0,0,-1,1};
int dy[4]={1,-1,0,0};
int main(){
	scanf("%d%d",&h,&w);
	getchar();
	int t=0;
	for(int i=1;i<=h;i++){
		for(int j=1;j<=w;j++){
			scanf("%c",&s[i][j]);
			if(s[i][j]=='.')
				d[i][j]=1e9;
			else{
				d[i][j]=0;
				x[t]=i;
				y[t++]=j;
			}
		}
		getchar();
	}
	int s=0,ans=0;
	while(s<t){
		int xx=x[s],yy=y[s++];
		for(int i=0;i<4;i++){
			int u=xx+dx[i];
			int v=yy+dy[i];
			if(u<1||u>h||v<1||v>w||d[u][v]<=d[xx][yy]+1)
				continue;
			d[u][v]=d[xx][yy]+1;
			ans=max(ans,d[u][v]);
			x[t]=u;
			y[t++]=v;
		}
	}
	printf("%d\n",ans);
}

B-LRUD Game

题意:给定棋盘,两个人移动棋子,每个人有n种操作,最后如果棋子还在盘子里,则输出YES,否则输出NO。

思路:从后往前推,如果中途区间非法,则失败,如果最后棋子开始的位置不在推出的区间内,则失败。

#include<bits/stdc++.h>
using namespace std;
char s[200005],t[200005];
int h,w,n,sr,sc;
int walk1(){
	int l=1,r=h;
	for(int i=n;i>=1;i--){
		if(t[i]=='U')
			r=min(h,r+1);
		else if(t[i]=='D')
			l=max(l-1,1);
		if(s[i]=='U')
			l++;
		else if(s[i]=='D')
			r--;
		if(l>r)
			return 1;
	}
	return (sr<l||sr>r); 
}
int walk2(){
	int l=1,r=w;
	for(int i=n;i>=1;i--){
		if(t[i]=='L')
			r=min(w,r+1);
		else if(t[i]=='R')
			l=max(l-1,1);
		if(s[i]=='R')
			r--;
		else if(s[i]=='L')
			l++;
		if(l>r)
			return 1;
	}
	return (sc<l||sc>r); 
}
int main(){
	scanf("%d%d%d",&h,&w,&n);
	scanf("%d%d",&sr,&sc);
	scanf("%s",s+1);
	scanf("%s",t+1);
	if(walk1()||walk2())
		puts("NO");
	else puts("YES");
}

C-Removing Coins

题意:有一棵树,每个节点都有一枚硬币,两个人轮流操作,每次可以选则一个节点删除里面的所有硬币,如果该节点硬币为0,则与他相邻的所有节点的硬币都转移到该节点上,如果最后谁无法操作,则谁输,另一个人赢。

思路:每次操作的结果要么是删除所有叶子节点,要么保留一个叶子节点,删除其他点。。。

#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+5;
int n,f[maxn],dep[maxn];
vector<int>g[maxn];
void dfs(int u,int fa){
	for(int i=0;i<g[u].size();i++)
		if(g[u][i]!=fa)
			dep[g[u][i]]=dep[u]+1,dfs(g[u][i],u);
}
int main(){
	f[0]=1;
	f[1]=0;
	scanf("%d",&n);
	for(int i=2;i<=n;i++)
		if(f[i-1]&&f[i-2])
			f[i]=0;
		else f[i]=1;
		int x,y;
	for(int i=2;i<=n;i++){
		scanf("%d%d",&x,&y);
		g[x].push_back(y);
		g[y].push_back(x);
	}
	dfs(1,0);
	int t=1;
	for(int i=2;i<=n;i++)
		if(dep[i]>dep[t])
			t=i;
	for(int i=1;i<=n;i++)
		dep[i]=0;
	dfs(t,0);
	t=0;
	for(int i=1;i<=n;i++)
		t=max(t,dep[i]);
	if(f[t])
		puts("First");
	else puts("Second");
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值