CodeVS2495 水叮當的舞步


標簽:IDA*

題目

題目傳送門

題目描述 Description

  水叮當得到了一塊五顏六色的格子形地毯作為生日禮物,更加特別的是,地毯上格子的顏色還能隨着踩踏而改變。
  為了討好她的偶像虹貓,水叮當決定在地毯上跳一支輕盈的舞來賣萌~~~

  地毯上的格子有N行N列,每個格子用一個0~5之間的數字代表它的顏色。
  水叮當可以隨意選擇一個0~5之間的顏色,然后輕輕地跳動一步,左上角的格子所在的聯通塊里的所有格子就會變成她選擇的那種顏色。這里連通定義為:兩個格子有公共邊,並且顏色相同。
  由於水叮當是施展輕功來跳舞的,為了不消耗過多的真氣,她想知道最少要多少步才能把所有格子的顏色變成一樣的。
輸入描述 Input Description

  每個測試點包含多組數據。
  每組數據的第一行是一個整數N,表示地攤上的格子有N行N列。
  接下來一個N*N的矩陣,矩陣中的每個數都在0~5之間,描述了每個格子的顏色。
  N=0代表輸入的結束。
輸出描述 Output Description

  對於每組數據,輸出一個整數,表示最少步數。
樣例輸入 Sample Input

2
0 0
0 0
3
0 1 2
1 1 2
2 2 1
0
樣例輸出 Sample Output

0
3
數據范圍及提示 Data Size & Hint

  對於30%的數據,N<=5
  對於50%的數據,N<=6
  對於70%的數據,N<=7
  對於100%的數據,N<=8,每個測試點不多於20組數據。

第二組樣例解釋:
  0 1 2 1 1 2 2 2 2 1 1 1
  1 1 2 –> 1 1 2 –> 2 2 2 –> 1 1 1
  2 2 1 2 2 1 2 2 1 1 1 1

來源:Nescafe 21

分析

黃學長題解

我們引入一個N*N的vis數組。左上角的格子所在的聯通塊里的格子標記為1。左上角聯通塊周圍一圈格子標記為2,其它格子標記為0。如果某次選擇了顏色c,我們只需要找出標記為2並且顏色為c的格子,向四周擴展,並相應地修改v標記,就可以不斷擴大標記為1的區域,最終如果所有格子標記都是1,那么顯然找到了答案。

code

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<algorithm>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define dep(i,a,b) for(int i=a;i>=b;i--)
#define ll long long
#define mem(x,num) memset(x,num,sizeof x)
#define reg(x) for(int i=last[x];i;i=e[i].next)
using namespace std;
inline ll read()
{
    ll f=1,x=0;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
const int dx[4]={0,1,0,-1},dy[4]={1,0,-1,0};
int Map[9][9],vis[9][9],n,lim,used[6];
bool ans;
int get(){
    int t=0;mem(used,0);
    rep(i,1,n)
        rep(j,1,n)
            if(!used[Map[i][j]]&&vis[i][j]!=1){
                used[Map[i][j]]=1;
                t++;
            }
    return t;
}
void dfs(int a,int b,int x){
    vis[a][b]=1;
    rep(i,0,3){
        int nx=a+dx[i],ny=b+dy[i];
        if(nx<1||nx>n||ny<1||ny>n||vis[nx][ny]==1)continue;
        vis[nx][ny]=2;
        if(Map[nx][ny]==x)dfs(nx,ny,x);
    }
}

int fill(int x){
    int t=0;
    rep(i,1,n)
        rep(j,1,n)
            if(vis[i][j]==2&&Map[i][j]==x){
                t++;
                dfs(i,j,x);
            }
    return t;
}
void search(int k){
    int v=get();
    if(!v)ans=1;
    if(k+v>lim||ans)return;
    int tmp[10][10];
    rep(i,0,5){
        memcpy(tmp,vis,sizeof vis);
        if(fill(i))search(k+1);
        memcpy(vis,tmp,sizeof vis);
    }
}

int main()
{
    while(true){
        mem(vis,0);ans=0;lim=-1;
        n=read();if(n==0)break;
        rep(i,1,n)
            rep(j,1,n)Map[i][j]=read();
        dfs(1,1,Map[1][1]);
        while(true){
            lim++;
            search(0);
            if(ans){printf("%d\n",lim);break;}
        }
    }
    return 0;
}

注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
  © 2014-2022 ITdaan.com