【NOIP2013模拟】水叮当的舞步

Description

给出一个N*N的网格,每个格子有它的颜色0~5。
每一次你可以选择一个颜色,然后把左上角的格子所在的联通块里的所有格子变成选择的那种颜色。这里的联通是指两个格子有公共边,并且颜色相同。
现在想问,最少需要多少次操作,才会使所有格子的颜色相同。
N<=8,数据组数<=20

Solution

玄学暴力题,各种无脑优化。
考虑到答案不会特别大,可以使用迭代加深。
设一个估价函数(高大上),表示最少还需要的步数,如果当前深度+估价函数>限制就退出。
复杂度玄学,O(跑得过),对于这类题,Czy大神有话要说

Code

#include<cstdio>
#include<cstring>
#include<algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define N 9
using namespace std;
int v[N][N],rev[N][N],a[N][N],id,n;
int g[4][2]={0,1,0,-1,1,0,-1,0};
void fill(int x,int y,int c) {
    v[x][y]=1;
    fo(i,0,3) {
        int xx=x+g[i][0],yy=y+g[i][1];
        if (xx>n||xx<1||yy>n||yy<1||v[xx][yy]==1) continue;
        v[xx][yy]=2;
        if (a[xx][yy]==c) fill(xx,yy,c);
    }
}
int pd() {
    int cnt=0;bool bz[6];memset(bz,0,sizeof(bz));
    fo(i,1,n) fo(j,1,n) if (v[i][j]!=1&&!bz[a[i][j]]) {
        bz[a[i][j]]=1;cnt++;
    }
    return cnt;
}
bool can(int c) {
    bool bz=0;
    fo(i,1,n) fo(j,1,n) if (v[i][j]==2&&a[i][j]==c) {
        fill(i,j,c);bz=1;
    }
    return bz;
}
bool dfs(int x) {
    int p=pd();
    if (x+p>id) return 0;
    if (!p) return 1;
    int rev[N][N];
    memcpy(rev,v,sizeof(rev));
    fo(i,0,5) {
        if (can(i)&&dfs(x+1)) return 1;
        memcpy(v,rev,sizeof(v));
    } 
    return 0;
}
int main() {
    for(scanf("%d",&n);n;scanf("%d",&n)) {
        fo(i,1,n) fo(j,1,n) scanf("%d",&a[i][j]);
        memset(v,0,sizeof(v));
        fill(1,1,a[1][1]);
        for(id=0;id<=n*n;id++) if (dfs(0)) break;
        printf("%d\n",id);
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值