1. 程式人生 > >【NOJ1006】【演算法實驗二】【回溯演算法】堡壘問題_方格類資料表示方法

【NOJ1006】【演算法實驗二】【回溯演算法】堡壘問題_方格類資料表示方法

1006.堡壘問題

時限:1000ms 記憶體限制:10000K  總時限:3000ms

描述

城堡是一個4×4的方格,為了保衛城堡,現需要在某些格子裡修建一些堡壘。城堡中的某些格子是牆,其餘格子都是空格,堡壘只能建在空格里,每個堡壘都可以向上下左右四個方向射擊,如果兩個堡壘在同一行或同一列,且中間沒有牆相隔,則兩個堡壘都會把對方打掉。問對於給定的一種狀態,最多能夠修建幾個堡壘。

輸入

每個測例以一個整數n(1<=n<=4)開始,表示城堡的大小。

接下來是n行字元每行n個,‘X’表示該位置是牆,‘.’表示該位置是空格。

n等於0標誌輸入結束。

輸出

每個測例在單獨的一行輸出一個整數:最多修建堡壘的個數。

#include <iostream>

using namespace std;

int n;      //城堡大小
int a[4][4];    //城堡方格,1==牆,0==空,-1==堡壘
                //左上角為方格[0,0]

int mcnt;   //最大堡壘個數
int cnt;    //當前已建堡壘個數

void dfs(int m);        //回溯深搜
bool ok(int i,int j);   //判斷方格[i,j]能否放置堡壘

int main()
{
    cin>>n;
    while(n){
        char c;
        for(int i=0;i<n;i++){
            for(int j=0;j<n;j++){
                cin>>c;
                if(c=='X')      //牆
                    a[i][j]=1;
                else            //空
                    a[i][j]=0;
            }
        }
        //初始化
        mcnt=0;
        cnt=0;

        dfs(0);

        cout<<mcnt<<endl;

        cin>>n;
    }

    return 0;
}

void dfs(int m)     //判斷序號為m的方格
{
    if(m==(n*n)){       //搜到最後一個方格
        if(mcnt<cnt)    //更新最大值
            mcnt=cnt;
    }
    else{
        int i=m/n;
        int j=m%n;
        if(ok(i,j)){     //若方格m內可以修建堡壘
            a[i][j]=-1;
            cnt++;
            dfs(m+1);
            cnt--;
            a[i][j]=0;
        }
        dfs(m+1);
    }
}

//函式功能:判斷方格[i,j]內能否放置堡壘
//不能放置條件:
//1.本方格是牆
//2.本方格的上方或左方有堡壘(中間無牆相隔)
//因為是按序號順序搜尋方格,因此不必判斷下方或右方(還未放置,必無堡壘)
bool ok(int i,int j)
{
    int x,y;
    if(a[i][j]==1)  return false;   //本方格是牆

    for(x=i-1,y=j;x>=0;x--){ //向上找
        if(a[x][y]==1)  break;
        if(a[x][y]==-1) return false;
    }

    for(x=i,y=j-1;y>=0;y--){ //向左找
        if(a[x][y]==1)  break;
        if(a[x][y]==-1) return false;
    }

    return true;
}

【後記】

1.做了幾道回溯,深深感覺dfs簡直就是套路,裡面多半是下面這種格式:

if (m==n)

    {......}

else

    {.......}

2.既然演算法是套路,那麼麻煩主要在於如何表示資料

一般來說,方格類資料用二維陣列表示,每個方格有兩個名字:序號m和位置[ i , j ]

預設左上角為序號0,位置為[ 0 , 0 ],如下圖所示: