BFS 搜索 Problem 1009 連連看

Problem ID:1009 連連看


簡單題意:一個棋盤上放了若干個棋子,如果兩個相同(位置不同)的棋子能用一條線連起來,且轉折次數不超過2次,則可將其消去。給出棋盤和棋子,以及試圖消去的兩個棋子位置。如果能消去,輸出“YES”,如果不能,輸出“NO”。


解題思路形成過程:利用BFS進行搜索,符合要求的下一步共有3個要求:

             ①:連線必須在棋盤內,不能從外面繞出去;

             ②:下一個目標區域的沒有以任何方向走過,或者新的走法轉折次數更少;

             ③:此區域無棋子(如果找到了目標直接return返回)。

            注意:如果選擇的兩個棋子類型不同,或其中任意一個位置沒有棋子,則須直接輸出“NO”。


感想: 一個不是太難的題,WA了16次………… 改了N久……  最後才發現WA的原因是如果是該輸出“NO”,主函數裏的條件該寫成對應的-1 而不是0……  反覆檢查居然沒有發現………… 

    還有就是中間有一個情況沒有考慮到…

    一開始用的DFS,會超時,後來又改成BFS寫的。不過如果剪枝處理的比較好,DFS應該也可以。

    第一次見識和學習了三維數組,挺好使。

    注意條件的整合,以提高代碼效率。

    無論如何…… 終於是AC了…


代碼:

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<queue>
using namespace std;
#define INF 10000
int cmap[1001][1001];
int mark[1001][1001][4];
int query[4];
int dir[4][2]={{-1,0},{1,0},{0,-1},{0,1}};
int n,m;
int BFS()
{
    queue<int>s;
    s.push(query[0]);       //隊列中4個元素爲一組,分別是當前行(r),當前列(c),當前方向(state),當前轉折次數(cnt)。
    s.push(query[1]);
    s.push(-1);
    s.push(-1);
    while(!s.empty())
    {
        int r=s.front();
        s.pop();
        int c=s.front();
        s.pop();
        int state=s.front();
        s.pop();
        int cnt=s.front();
        s.pop();

        for(int i=0;i<4;++i){   //i也代表了移動的方向。i=0,1,2,3分別代表了上,下,左,右。
            int t_cnt=cnt;
            if(i!=state)
                ++t_cnt;
            if(t_cnt>2)
                continue;
            if(r+dir[i][0]==query[2]&&c+dir[i][1]==query[3])
                return 1;
            if(r+dir[i][0]>=0&&r+dir[i][0]<n&&c+dir[i][1]>=0&&c+dir[i][1]<m)
                if(mark[r+dir[i][0]][c+dir[i][1]][i]>t_cnt)       //沒走過或者新的路徑轉折次數更少
                    if(cmap[r+dir[i][0]][c+dir[i][1]]==0){
                       // cout<<r<<' '<<c<<' '<<"go"<<endl;
                        s.push(r+dir[i][0]);
                        s.push(c+dir[i][1]);
                        s.push(i);
                        s.push(t_cnt);
                        mark[r+dir[i][0]][c+dir[i][1]][i]=t_cnt;
          }
        }
    }
    return -1;
}
int main()
{
    freopen("1.txt","r",stdin);
    while(1)
    {
        scanf("%d%d",&n,&m);
        if(n==0)
            return 0;
        for(int i=0;i<n;++i)
            for(int j=0;j<m;++j)
                cin>>cmap[i][j];
        int q;
        scanf("%d",&q);
        for(int i=0;i<q;++i){
            scanf("%d%d%d%d",&query[0],&query[1],&query[2],&query[3]);
            --query[0];
            --query[1];
            --query[2];
            --query[3];
            memset(mark,INF,sizeof(mark));//INF
            if(cmap[query[0]][query[1]]!=cmap[query[2]][query[3]]||cmap[query[0]][query[1]]==0||cmap[query[2]][query[3]]==0||(query[0]==query[2]&&query[1]==query[3]))
                printf("NO\n");
            else if(BFS()==1)
                printf("YES\n");
            else if(BFS()==-1)
                printf("NO\n");
        }
    }
}


發佈了48 篇原創文章 · 獲贊 4 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章