1. 程式人生 > >codevs2495 水叮當的舞步(IDA*)

codevs2495 水叮當的舞步(IDA*)

amp 裏的 ogg ted mark mes -- a* memcpy

2495 水叮當的舞步

時間限制: 1 s 空間限制: 32000 KB 題目等級 : 鉆石 Diamond
題目描述 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

分類標簽 Tags

啟發式搜索 叠代搜索 搜索 技術分享
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int s,n,map[9][9];
int xx[4]={1,-1,0,0},yy[4]={0,0,-1,1};
bool ans;
bool judans()
{
    int t=map[1][1];
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
            if(map[i][j]!=t)return 0;
    return 1;
}
void change(int a,int b,int x,int y)
{
    map[a][b]=y;
    for(int i=0;i<4;i++)
    {
        int nowx=a+xx[i],nowy=b+yy[i];
        if(nowx<1||nowy<1||nowx>n||nowy>n)continue;
        if(map[nowx][nowy]==x)change(nowx,nowy,x,y);
        }
}
void dfs(int now)
{
    if(now==s){if(judans())ans=1;return;}
    if(ans)return;
    for(int c=0;c<=5;c++)
    {
        int a[9][9];
        if(map[1][1]==c) continue;
        for(int i=1;i<=n;i++)
          for(int j=1;j<=n;j++)
            a[i][j]=map[i][j];
        change(1,1,map[1][1],c);
        dfs(now+1);
        for(int i=1;i<=n;i++)
          for(int j=1;j<=n;j++)
            map[i][j]=a[i][j];
    }
}
int main()
{
    while(1)
    {
        scanf("%d",&n);ans=0;
        if(n==0)break;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                scanf("%d",&map[i][j]);
        for(s=0;;s++)
        {
            dfs(0);
            if(ans){printf("%d\n",s);break;}
            }
    }
    return 0;
}
暴力

/*
左上角的格子所在的聯通塊裏的格子標記為1。左上角聯通塊周圍一圈格子標記為2,
其它格子標記為0。如果某次選擇了顏色c,
只需要找出標記為2並且顏色為c的格子,向四周擴展
,並相應地修改v標記,就可以不斷擴大標記為1的區域,
最終如果所有格子標記都是1
*/ 
#include<iostream>
#include<cstring>
#include<cstdio>

using namespace std;
int s,n,map[9][9],mark[9][9];
int xx[4]= {1,-1,0,0},yy[4]= {0,0,-1,1},used[6];
bool ans;

int get()
{
    int t=0;
    memset(used,0,sizeof(used));
    for(int i=1; i<=n; i++)
      for(int j=1; j<=n; j++)
        if(!used[map[i][j]]&&mark[i][j]!=1)
        {
            used[map[i][j]]=1;
            t++;
        }return t;
}

void dfs(int a,int b,int x)
{
    mark[a][b]=1;
    for(int i=0; i<4; i++)
    {
        int nowx=a+xx[i],nowy=b+yy[i];
        if(nowx<1||nowy<1||nowx>n||nowy>n||mark[nowx][nowy]==1)continue;
        mark[nowx][nowy]=2;
        if(map[nowx][nowy]==x)dfs(nowx,nowy,x);
    }
}

int fill(int x)
{
    int t=0;
    for(int i=1; i<=n; i++)
      for(int j=1; j<=n; j++)
        if(mark[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>s||ans)return;
    int temp[10][10];
    for(int i=0; i<=5; i++)
    {
        memcpy(temp,mark,sizeof(mark));
        if(fill(i))search(k+1);
        memcpy(mark,temp,sizeof(mark));
    }
}

int main()
{
    while(1)
    {
        memset(mark,0,sizeof(mark));
        scanf("%d",&n);
        ans=0;
        if(n==0)break;
        for(int i=1; i<=n; i++)
            for(int j=1; j<=n; j++)
                scanf("%d",&map[i][j]);
        dfs(1,1,map[1][1]);
        for(s=0;;s++)
        {
            search(0);
            if(ans){printf("%d\n",s); break;}
        }
    }
    return 0;
}

codevs2495 水叮當的舞步(IDA*)