变色龙的题解

在一个的,每个格子都有一种给定颜色的方格矩阵上,有一只变色龙在处,他会在这个方格矩阵上移动。
移动规则如下:

  1. 变色龙只能朝相邻于当前方格的一个方格(上下左右)上移动一格,且不能移出边界。
  2. 众所周知,变色龙特异的身体会使自己的身体颜色随着环境颜色的变化而变化。所以如果移动到的方格和当前方格的颜色不同,变色龙颜色变化次数会+1,否则颜色变化次数不变。

然而变色龙并不希望能移动的步数最小,它希望颜色的变化次数最小。
它告诉你每个格子的颜色,以及它当前所在的格子,它希望你告诉它从当前格子分别到每个格子的最小颜色变化次数是多少。

错点

b f s bfs bfs p r i o r i t y priority priority_ q u e u e queue queue 优化写假了。

分析

最短路问题。

为什么能使用 d i j dij dij 跑最短路?明显会 T T T 啊!

点数: 2000 × 2000 = 400 , 0000 2000 \times 2000=400,0000 2000×2000=400,0000

边数:小学奥数之等差数列

0 + 4 + ⋯ + 7996 ⏟ 2000 项 = ( 7996 + 0 ) × 2000 ÷ 2 = 7996 × 1000 = 799 , 6000 \begin{matrix}\underbrace{0+4+\cdots+7996}\\2000项\end{matrix}=(7996+0) \times 2000 \div 2=7996 \times 1000=799,6000 0+4++79962000=(7996+0)×2000÷2=7996×1000=799,6000

我们知道 d i j dij dij 的复杂度是 O ( n log ⁡ m ) O(n \log m) O(nlogm) 简单计算一下 log ⁡ m = log ⁡ 7996000 ≈ 26 \log m=\log 7996000 \approx 26 logm=log799600026 26 × 4000000 = 1 , 0400 , 0000 > 1 , 0000 , 0000 ‬ 26 \times 4000000=1,0400,0000 > 1,0000,0000‬ 26×4000000=1,0400,0000>1,0000,0000

所以显然是会 T T T 掉的~~(除非玄学卡常,比如:等式展开之类的)~~

b f s bfs bfs 的期望复杂度是 O ( n + m ) O(n+m) O(n+m) 的。

b f s bfs bfs 大概就是这种写法

q.push((node){xx,yy});
ans[xx][yy]=0;
while(q.size()){
	node f=q.front();
	q.pop();
	for(int i=0;i<4;i++){
		int x=f.x+dx[i],y=f.y+dy[i];
		if(x>=1&&x<=n&&y>=1&&y<=m){
			int as=ans[f.x][f.y];
			if(a[x][y]!=a[f.x][f.y])as++;
			if(as<ans[x][y])ans[x][y]=as,q.push((node){x,y});
		}
	}
}

总代码

#include <bits/stdc++.h>
using namespace std;
template<typename T>inline void read(T &FF){
	T RR=1;FF=0;char CH=getchar();
	for(;!isdigit(CH);CH=getchar())if(CH=='-')RR=-1;
	for(;isdigit(CH);CH=getchar())FF=(FF<<1)+(FF<<3)+(CH^48);
	FF*=RR;
}
template<typename T>void write(T x){
	if(x<0)putchar('-'),x*=-1;
	if(x>9)write(x/10);
	putchar(x%10+48);
}
struct node{
    int x,y;
};
const int MAXN=2000+10;
int n,m,xx,yy,a[MAXN][MAXN],ans[MAXN][MAXN];
int dx[4]={-1,1,0,0};
int dy[4]={0,0,-1,1};
queue<node>q;
int main(){
	memset(ans,0x3f,sizeof(ans));
	read(n);read(m);read(xx);read(yy);
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++)
			read(a[i][j]);
	q.push((node){xx,yy});
	ans[xx][yy]=0;
	while(q.size()){
		node f=q.front();
		q.pop();
		for(int i=0;i<4;i++){
			int x=f.x+dx[i],y=f.y+dy[i];
			if(x>=1&&x<=n&&y>=1&&y<=m){
				int as=ans[f.x][f.y];
				if(a[x][y]!=a[f.x][f.y])as++;
				if(as<ans[x][y])ans[x][y]=as,q.push((node){x,y});
			}
		}
	}
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++)
			cout<<ans[i][j]<<" ";
		cout<<endl;
	}
	return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值