1. 程式人生 > >洛谷【P1172】安全逃離題解

洛谷【P1172】安全逃離題解

get 測評 upload 也有 加粗 end 北方 幫助 情況

題目

題目描述

農夫john最近在研究如果發生重大事故,如何讓農場裏的奶牛逃離問題。他想要確信在緊急情況下,所有的奶牛都有一個安全逃離方案。因為在緊急情況下,奶牛們都會失去觀察和判斷能力,所以最近john一直在教奶牛們逃離的方法,他的方法很簡單,就是任何時候都只向北方或東方逃離,北方是行坐標減1的方向,東方是列坐標加1的方向。奶牛們雖笨,不過這一點事關自己的生命,所以他們牢記在心,而且也一定會這麽做。

當然也會出問題,奶牛們在逃離的方向上會橫沖直撞,為了阻止奶牛之間互相沖撞造成傷害,john要求任何一個奶牛的逃離路線不能經過其它奶牛的初始位置。一個逃離方案是安全的如果它能夠滿足上面的要求,反之它就是不安全的。

奶牛們所在的土地(農場)被劃分成了rr行和cc列的一個矩形地圖。奶牛們都待在這個矩形中的某一個位置。

請幫助john確定給定的一個地圖上是否存在一個安全的逃離方案。

比如,下面的兩個圖:

技術分享圖片

左邊的例子表示了一個能夠安全逃離的地圖,因為沒有任何一個奶牛的逃離路線上包括其他奶牛。右邊的例子表示了一個不安全的地圖,因為位於(4,1)(4,1)的奶牛不論是向東逃離還是向北逃離,它的路線上都會有別的奶牛,從這個圖中拿掉任意一頭奶牛,這個地圖都會變成安全的。

輸入輸出格式

輸入格式

\(1\)行:兩個整數\(r,c\),用1個空格隔開,表示矩形的行數和列數(均 \(\le 50\))。
\(2\)行:一個整數\(n\)

,表示奶牛的個數(\(\le 100\))。
\(3\)\(n+2\)行:共\(n\)行,每行有\(2\)個整數,之間用\(1\)個空格隔開,分別表示這頭奶牛所在的行和列。
每輸入完一行後,會輸入多余的字符!!!

輸出格式

如果這塊土地是安全的,輸出\(0\)
如果移走任意一頭奶牛這塊土地還是不安全,輸出\(-1\)否則輸出移走的那頭奶牛的編號,如果有多個奶牛滿足要求,輸出所有的數

輸入輸出樣例

輸入樣例

5 5
5
1 1
2 4
3 1
2 2
2 1

輸出樣例

1
5

題解

這一題的題目有問題(我在百度上查了,所有題目都是錯的。多虧了洛谷的在線測評,把題解復制在上面執行,就可以知道題目錯誤了)。我整整研究了一天才研究出來。最後,我是在另一個人提交的AC程序上找出了我的錯誤。這個錯誤你根本是不可能想到的(雖然我不知道以前的人是怎麽發現的),這個錯誤是就是我在題目中加粗的字

其實這個問題我在一個OJ上也有註意到(那個OJ可以下載不完整的數據),但是我並不知道這是一個漏洞。
這道題的思路就是模擬,首先遍歷所有的奶牛,若全部安全,則輸出0,結束。如果不是全部安全的,則每次將一只奶牛刪除,再遍歷全部,看看是否全是安全的,如果是,則輸出該奶牛編號,直到所有情況都遍歷完了,再討論-1的情況。
代碼如下:

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
int m[51][51],h,l,n;
struct cow{     //結構體,也可以用x[101]和y[101] 
  int x,y;
};
cow a[101];
int anquan(int x,int y){     //每頭奶牛安全的條件 
  int t1=1,t2=1;
  for(int i=1;i<x;i++) if(m[i][y]) {t1=0;break;}     //如果北面有奶牛,那麽t1=0 
  for(int i=y+1;i<=l;i++) if(m[x][i]) {t2=0;break;}     //如果東面有奶牛,那麽t2=0 
  if(t1==0&&t2==0) return 0; else return 1;     //如果兩邊都有奶牛,則不安全,反之安全 
}
int qaq(){     //所有奶牛都安全 
  for(int i=1;i<=h;i++) for(int j=1;j<=l;j++) if(m[i][j]) if(!(anquan(i,j))) return 0;     //遍歷整個農場,如果有奶牛不安全,那麽返回0 
  return 1;     //否則返回1 
}
int aq(int x,int y){     //去掉一只奶牛後安全
  m[x][y]=0;     //刪除奶牛
  return qaq();
}
int main()
{
  int temp=0;
  char s[100];
  cin>>h>>l>>n;
  memset(a,0,sizeof(a));memset(m,0,sizeof(m));     //初始化 
  for(int i=1;i<=n;i++){
    cin>>a[i].x>>a[i].y;     //輸入 
    m[a[i].x][a[i].y]=i;     //也可以賦值為1 
    gets(s);
  }
  if(qaq()) {cout<<0;return 0;}     //如果全部安全,輸出0,結束 
  for(int i=1;i<=n;i++){
    if(aq(a[i].x,a[i].y)) /*如果去掉後安全*/if(!temp) /*如果是第一次輸出*/cout<<i,temp++; else cout<<endl<<i; 
    m[a[i].x][a[i].y]=i;     //這步非常重要,不然第二次執行的時候就刪除了兩只奶牛 
  }
  if(!temp) cout<<-1;     //如果刪掉任何一只奶牛都不安全,輸出-1 
  return 0;
}

洛谷【P1172】安全逃離題解