小遊戲 (最少線段連線問題)

 遊戲在一個分割成w * h個長方格子的矩形板上進行。如圖所示,每個長方格子上可以有一張遊戲卡片,也可以沒有。當下面的情況滿足時,我們認爲兩個遊戲卡片之間有一條路徑相連: 
   路徑只包含水平或者豎直的直線段。路徑不能穿過別的遊戲卡片。但是允許路徑臨時離開矩形板。 
   下面是一個例子:
這裏在(1, 3)和(4, 4)處的遊戲卡片是可以相連的。而在 (2, 3) 和 (3, 4) 處的遊戲卡是不相連的,因爲連接他們的每條路徑都必須要穿過別的遊戲卡片。 

   你現在要在小遊戲裏面判斷是否存在一條滿足題意的路徑能連接給定的兩個遊戲卡片。


這道題最早遇見是在高二的縣裏的模擬賽的時候,感覺是一個經典的問題。

分析,首先因爲要求是最少的線段,實際就是用最少的轉彎,那就每個方向光搜出去應該是能到的最遠處內的所有點都是應該在該層中被加入隊列的。

於是按照線段的轉折次數爲層數進行光搜即可。其中要注意一些細節。


該題出現在P大的編程網格上,歲月匆匆感慨萬千,因爲細節沒有處理好,導致大數據上WA了若干次。

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cstring>
#include <queue>


using namespace std;


const int maxN = 100+10;
const int dir[4][2]= {0,1,0,-1,-1,0,1,0};


char s[maxN], map[maxN][maxN];
int sx,sy,tx,ty,n,m,ans;
int f[maxN][maxN][4],arrive[maxN][maxN][4];
struct Node{
       int x,y,Dir;       
}node,newNode;
queue<Node> q;
bool inside(int x,int y)
{
       return (x>=0 && x<=n+1 && y>=0 && y<=m+1);  
}
bool ok()
{
       memset(arrive,0,sizeof(arrive));
       memset(f,127,sizeof(f));
       bool canArrive = false;
       while (!q.empty()) q.pop();
       for (int k = 0; k < 4;++k)
       {
           node.x = sx; node.y = sy; node.Dir = k;
           q.push(node);
           f[sx][sy][k]=1;
           arrive[sx][sy][k]=true;                 
       }
       while (!q.empty())
       {
           Node now = q.front();
           q.pop();
           arrive[now.x][now.y][now.Dir] == false;
           for (int k = 0; k < 4; ++k)
           for (int step = 1; step <= maxN ; ++step)
           {
               int x=now.x+dir[k][0]*step;
               int y=now.y+dir[k][1]*step;
               if ( !inside(x,y)) break;
               if (tx == x && ty == y) 
               {
                    f[x][y][k]=min(f[x][y][k],
                    f[now.x][now.y][now.Dir]+(now.Dir != k));
                    canArrive = true; 
               }
               if (map[x][y] == 'X' ) break;
               if (f[now.x][now.y][now.Dir]+(now.Dir != k)< f[x][y][k])
               {
                    f[x][y][k]=f[now.x][now.y][now.Dir]+(now.Dir != k);
                    if (!arrive[x][y][k])
                    {
                       arrive[x][y][k]=true;
                       newNode.x = x; newNode.y = y; newNode.Dir = k;
                       q.push(newNode);
                    }                  
               }                  
           }                    
       }   
       return canArrive;
}
int main()
{
          int Test = 0;
          while (scanf("%d%d",&m,&n)==2)
          {
                if (m==0  && n==0) break;
                getchar();
                printf("Board #%d:\n",++Test);
                for (int i = 0; i <= n+1; ++i)
                    for (int j = 0; j <= m+1; ++j) map[i][j]='S';
                for (int i = 1;i <= n; ++i) 
                {
                         gets(s);
                         for (int j = 1; j <= m ;++j)
                             map[i][j] = s[j-1];
                }
                
                int Pair = 0;
                while(scanf("%d%d%d%d",&sy,&sx,&ty,&tx))
                {
                       if (sx+sy+tx+ty == 0) break;
                       if (!ok()) printf("Pair %d: impossible.\n",++Pair);
                       else 
                       {
                            int ans = maxN * maxN;
                            for (int k = 0 ; k < 4; ++k)
                            ans=min(ans,f[tx][ty][k]);
                            printf("Pair %d: %d segments.\n",++Pair,ans);     
                       }   
                }    
          }
          return 0;    
}



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