广搜的变形+最短路思想 变色龙
#include<cstdio> #include<queue> #include<cstring> #include<algorithm> using namespace std; const int maxn=2500; int map[maxn][maxn]; int n,m,x,y; int dis[maxn][maxn]; struct node { int x,y,dis; bool operator <(const node &a) const { return dis>a.dis;//用大根堆定义小于号为大于,这样每回取出的就是距离最小的,相当于广搜 } }; priority_queue<node> q; int xx[5]={0,1,0,0,-1}; int yy[5]={0,0,1,-1,0}; void dijkstra() { memset(dis,127,sizeof(dis)); dis[x][y]=0; node pos; pos.x=x; pos.y=y; pos.dis=0; q.push(pos); while(q.size()) { int x=q.top().x; int y=q.top().y; int d=q.top().dis; q.pop(); for(int i=1;i<=4;i++) { int fx=x+xx[i]; int fy=y+yy[i]; if(fx<=0||fx>n||fy<=0||fy>m) continue; int op=1;//fx,fy与x,y之间的边的大小 if(map[fx][fy]==map[x][y]) op=0; if(dis[fx][fy]>d+op) { dis[fx][fy]=d+op; pos.x=fx; pos.y=fy; pos.dis=dis[fx][fy]; q.push(pos); } } } } int main() { scanf("%d%d%d%d",&n,&m,&x,&y); for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) { scanf("%d",&map[i][j]); } } dijkstra(); for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) { printf("%d ",dis[i][j]); } printf("\n"); } return 0; }
题目背景
在一个 N×MN×M 的,每个格子都有一种给定颜色的方格矩阵上,有一只变色龙在第 XX 行第 YY 列处,他会在这个方格矩阵上移动。
移动规则如下:
变色龙只能朝相邻于当前方格的一个方格(上下左右)上移动一格,且不能移出边界。
众所周知,变色龙特异的身体会使自己的身体颜色随着环境颜色的变化而变化。所以如果移动到的方格和当前方格的颜色不同,变色龙颜色变化次数会+1,否则颜色变化次数不变。
然而变色龙并不希望能移动的步数最小,它希望颜色的变化次数最小。
它告诉你每个格子的颜色,以及它当前所在的格子,它希望你告诉它从当前格子分别到每个格子的最小颜色变化次数是多少。
输入格式
第一行包括四个正整数N,M,X,YN,M,X,Y,描述矩阵大小以及变色龙起点的坐标。
输出格式
NN 行每行 MM 个非负整数,描述从起点开始出发到每个点的最少颜色变化次数。
样例
input
5 5 3 3 1 1 3 1 1 1 3 3 3 1 3 2 2 2 3 1 4 4 4 6 1 1 1 5 1
output
2 2 1 2 2 2 1 1 1 2 1 0 0 0 1 2 1 1 1 2 2 2 2 2 3
数据范围
时间限制:1s
空间限制:256M
颜色大小在[1,100][1,100]中,
测试点编号 | N,MN,M范围 |
---|---|
1-3 | 1≤N,M≤51≤N,M≤5 |
4-5 | 1≤N,M≤1001≤N,M≤100 |
6-7 | 1≤N,M≤5001≤N,M≤500 |
8-10 | 1≤N×M≤1000000,1≤N,M≤20001≤N×M≤1000000,1≤N,M≤2000 |