AtCoder Beginner Contest 289 题解

D - Step Up Robot

大意:
格子阶梯,给定一步可以走的步数选择,不能后退,问从0开始能否走到n

思路:
dfs+记忆化

code

#include
using namespace std;
#define ll int
#define endl '\n'
const ll N=2e5+10;
ll n,m;
ll a,o;
ll mas[N];
ll num[N];
ll vis[N];
ll ans[N];
bool dfs(ll id)
{
	if(ans[id]!=-1) return ans[id]; 
	if(vis[id]) return 0;
	if(id>o) return 0;
	if(id==o) return 1;
	for(int i=1;i<=n;++i)
	{
		if(dfs(id+mas[i])) return ans[id]=1;
	}
	return ans[id]=0;
}
void solve()
{
	cin>>n;
	memset(ans,-1,sizeof ans);
	for(int i=1;i<=n;++i) cin>>mas[i];
	cin>>m;
	for(int i=1;i<=m;++i)
	{
		cin>>a;
		vis[a]=1;
	}
	cin>>o;
	cout<<(dfs(0)?"Yes":"No")<>t;while(t--)
	solve();
	return 0;
}

E - Swap Places

大意:
一张简单图,每一个点有一个颜色(1或0),两个点从分别从1和n出发,同时走下一步,且两者下一步的颜色必须不同,问能否实现分别到达n和1.如果可以,求最小步数

思路:
因为点数和边数都不多,我们可以直接记录两个点的中间状态,然后bfs一下就可以了

初始状态是(1,n),最终状态是(n,1)

code

#include
using namespace std;
#define ll long long
#define endl '\n'
#define mk make_pair
const ll N=2010;
const ll inf=1e9;
ll n,m;
vector vt[N];
ll mp[N][N];
ll col[N];
void bfs()
{
	queue> q;
	q.push(mk(1,n));
	mp[1][n]=0;
	while(!q.empty())
	{
		ll x=q.front().first;
		ll y=q.front().second;
		q.pop();
		for(auto xx:vt[x])
		{
			for(auto yy:vt[y])
			{
				if(mp[xx][yy]!=inf) continue;
				if(col[xx]==col[yy]) continue;
				mp[xx][yy]=mp[x][y]+1;
				q.push(mk(xx,yy));
				if(mp[n][1]!=inf) return;
			}
		}
		
		
	}
		
}
void solve()
{
	cin>>n>>m;
	for(int i=1;i<=n;++i) cin>>col[i],vt[i].clear();
	for(int i=1;i<=n;++i)
	{
		for(int j=1;j<=n;++j) mp[i][j]=inf;
	}
	for(int i=1;i<=m;++i)
	{
		ll a,b;
		cin>>a>>b;
		vt[a].push_back(b);
		vt[b].push_back(a);
	}
	bfs();
	cout<<(mp[n][1]!=inf?mp[n][1]:-1)<>t;while(t--)
	solve();
	return 0;
}

F - Teleporter Takahashi

大意:
二维平面,给定起点A和终点B,要求从A走到B。

规则如下,每次在一个选定区域内选择一个坐标均为整数的点C,移动到关于点C对称的点。

如果能实现,输出每次操作选定的对称点

选定区域:R:={(x,y)∣a−0.5≤x≤b+0.5,c−0.5≤y≤d+0.5}

思路:

为什么我会想到投影的方向去。。。)

不难发现,如果我们能够实现每次只改变横坐标/纵坐标的话,是可以贪心解决该问题的。更进一步,在不改变横坐标的情况下,如果连续两次选择的点的纵坐标相差=1,那么最后的实际效果是纵坐标变化=2,这是改变的最小差值。所以一个能实现的前提就是:起终点的坐标差值为偶数

接着,每次改变2的话,贪心一下就好了。因为如果我们只改变纵坐标的话,第一次选(a,c),第二次选(a,c+1),可以发现横坐标会回到原位

但是还有a=b或者c=d的情况(wa烂了)

自行体会吧,有些坑还是得自己去踩

code

#include
using namespace std;
#define ll long long
#define endl '\n'
#define mk make_pair
const ll N=2010;
const ll inf=1e9;
ll n,m;
ll a,b,c,d;
ll sx,sy,tx,ty;
bool f1,f2;
void solve()
{
	cin>>sx>>sy>>tx>>ty;
	cin>>a>>b>>c>>d;
	if(abs(sx-tx)%2||abs(sy-ty)%2)
	{
		cout<<"No"<0)
	{
		cout<0)
	{
		cout<>t;while(t--)
	solve();
	return 0;
}

G

详见我的另一篇博客

Ex

不会

你可能感兴趣的:(比赛题解,思维题,图论,深度优先,算法,图论)