变色龙的题解

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

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

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

错点

bfsbfsprioritypriority_queuequeue 优化写假了。

分析

最短路问题。

为什么能使用 dijdij 跑最短路?明显会 TT 啊!

点数:2000×2000=400,00002000 imes 2000=400,0000

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

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

我们知道 dijdij 的复杂度是 O(nlogm)O(n log m) 简单计算一下 logm=log799600026log m=log 7996000 approx 2626×4000000=1,0400,0000>1,0000,000026 imes 4000000=1,0400,0000 > 1,0000,0000‬

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

bfsbfs 的期望复杂度是 O(n+m)O(n+m) 的。

bfsbfs 大概就是这种写法

q.push((node){xx,yy,0});
	while(q.size()){
	node f=q.top();
	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(){
	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,0});
	while(q.size()){
		node f=q.top();
		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;
}
原文地址:https://www.cnblogs.com/zhaohaikun/p/12816944.html