变色龙C++

题目描述
在一个的n*m,每个格子都有一种给定颜色的方格矩阵上,有一只变色龙在(x,y)处,他会在这个方格矩阵上移动。 移动规则如下: 1.变色龙只能朝相邻于当前方格的一个方格(上下左右)上移动一格,且不能移出边界。 2.众所周知,变色龙特异的身体会使自己的身体颜色随着环境颜色的变化而变化。所以如果移动到的方格和当前方格的颜色不同,变色龙颜色变化次数会+1,否则颜色变化次数不变。 然而变色龙并不希望能移动的步数最小,它希望颜色的变化次数最小。 它告诉你每个格子的颜色,以及它当前所在的格子,它希望你告诉它从当前格子分别到每个格子的最小颜色变化次数是多少。 (注:两维的坐标描述都是从1开始,1-N。)

输入格式
第一行包括三个正整数,n,m,x,y描述矩阵大小以及出发的方格坐标。 之后n行每行m个正整数,描述着一个方格矩阵上每个方格的颜色。

输出格式
n行每行m个非负整数,描述从起点开始出发到每个点的最少颜色变化次数。

数据范围与提示
1<=n,m<=2000

输入样例

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

输出样例

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

代码如下:

#include<bits/stdc++.h>
#define FT first
#define SC second
#define PB push_back
#define MP make_pair
#define REP(i, l, r) for(int i = (l); i <= (r); i++)
#define PER(i, r, l) for(int i = (r); i >= (l); i--)
#define FOR(i, n) for(int i = 0; i < (n); i++)
#define ROF(i, n) for(int i = (n) - 1; i >= 0; i--)
#define VEP(i, x) for(int i = 0; i < x.size(); i++)
#define DFOR(i, x, y) for(int i = hd[x], y = e[i].to; i; i = e[i].nxt, y = e[i].to)
#define MEM(a, b) memset(a, b, sizeof(a))
#define pos(x, y) ((x - 1) * m + y)
#define rint read<int>()
#define rll read<LL>()
 
using namespace std;
typedef long long LL;
typedef long double LD;
typedef pair<int, int> PI;
const int inf = 0x7fffffff;
const int MOD = 1000000007;
 
template <typename tn>
inline tn read(){
    char ch; tn f = 1;
    while (!isdigit(ch = getchar())) if (ch == '-') f = -1;
    tn x = ch - '0';
    while (isdigit(ch = getchar())) x = x * 10 + ch - '0';
    return x * f;
}
template <typename tn> inline void cmax(tn &a, tn b){ if (a < b) a = b; }
template <typename tn> inline void cmin(tn &a, tn b){ if (a > b) a = b; }
 
const int dx[4] = {0, 1, 0, -1};
const int dy[4] = {1, 0, -1, 0};
const int N = 1000000 + 5;
int d[N], color[N], n, m, x, y, l, r;
PI q[N];
int work(int x, int y){
    FOR(i, 4){
        int tx = x + dx[i], ty = y + dy[i];
        if (tx >= 1 && tx <= n && ty >= 1 && ty <= m)
            if (color[pos(x, y)] == color[pos(tx, ty)]) 
                if (!~d[pos(tx, ty)] || d[pos(tx, ty)] > d[pos(x, y)]) d[pos(tx, ty)] = d[pos(x, y)], work(tx, ty);
                else;
            else 
                if (!~d[pos(tx, ty)]) d[pos(tx, ty)] = d[pos(x, y)] + 1, q[++r] = MP(tx, ty);
    }
}
int main(){
    //freopen("color.in", "r", stdin);
    //freopen("color.out", "w", stdout);
    n = rint, m = rint, x = rint, y = rint;
    MEM(d, -1);
    REP(i, 1, n) REP(j, 1, m) scanf("%d", &color[pos(i, j)]);
    for (d[pos(x, y)] = 0, q[l = r = 1] = MP(x, y); l <= r; ++l) work(q[l].FT, q[l].SC);
    REP(i, 1, n) REP(j, 1, m) printf("%d%c", d[pos(i, j)], " \n"[j == m]);
}

原文连接:https://ask.csdn.net/questions/7635053

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值