USACO-Section2.1 The Castle (深度优先搜索)
生活随笔
收集整理的這篇文章主要介紹了
USACO-Section2.1 The Castle (深度优先搜索)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
2017-8-3
題目描述
知道城堡有多少個房間,每個房間有多大 把一面單獨的墻(指兩個單位間的墻)拆掉以形成一個更大的房間解答
代碼寫的好長...代碼
/* ID: 18795871 PROG: castle LANG: C++ */ #include<iostream> #include<cstring> #include<fstream> using namespace std; const int N = 50;ifstream fin("castle.in"); ofstream fout("castle.out");struct{bool d,x,n,b;int x1,x2,y1,y2,a; }s[N+2][N+2];int r,c; int m,cnt,sum; bool f[N+1][N+1];void init(){ //根據所給條件判斷哪里有墻 int t;fin>>c>>r;for (int i=1;i<=r;i++){for (int j=1;j<=c;j++){fin>>t;switch(t){ //零的時候全為默認值 case(1):s[i][j].x=true;break;case(2):s[i][j].b=true;break;case(4):s[i][j].d=true;break;case(8):s[i][j].n=true;break;case(3):s[i][j].x=true;s[i][j].b=true;break;case(5):s[i][j].x=true;s[i][j].d=true;break;case(6):s[i][j].b=true;s[i][j].d=true;break;case(9):s[i][j].x=true;s[i][j].n=true;break;case(10):s[i][j].b=true;s[i][j].n=true;break;case(12):s[i][j].d=true;s[i][j].n=true;break;case(7):s[i][j].x=true;s[i][j].b=true;s[i][j].d=true;break;case(11):s[i][j].x=true;s[i][j].b=true;s[i][j].n=true;break;case(13):s[i][j].x=true;s[i][j].d=true;s[i][j].n=true;break;case(14):s[i][j].b=true;s[i][j].d=true;s[i][j].n=true;break;case(15):s[i][j].b=true;s[i][j].d=true;s[i][j].x=true;s[i][j].n=true;}}} }bool con(int i,int j){ //是否越界 if (i>r||j>c||i<1||j<1) return false;return true; }void dfs(int i,int j){ //深搜求出連通的房間數以及每個房間相應格數 if (!s[i][j].b&&con(i-1,j)&&!f[i-1][j]){f[i-1][j]=true;cnt++;dfs(i-1,j);}if (!s[i][j].n&&con(i+1,j)&&!f[i+1][j]){f[i+1][j]=true;cnt++;dfs(i+1,j);}if (!s[i][j].d&&con(i,j+1)&&!f[i][j+1]){f[i][j+1]=true;cnt++;dfs(i,j+1);}if (!s[i][j].x&&con(i,j-1)&&!f[i][j-1]){f[i][j-1]=true;cnt++;dfs(i,j-1);} }void cal(){ //a用來確定是否在同一房間內 for (int i=1;i<=r;i++){for (int j=1;j<=c;j++){if (f[i][j]){if (!s[i][j].x1&&!s[i][j].x2&&!s[i][j].y1&&!s[i][j].y2){s[i][j].a=sum;}if (s[i][j].d&&!s[i][j].x1){s[i][j].x1=cnt; //東面對應房間的格子數}if (s[i][j].x&&!s[i][j].x2){s[i][j].x2=cnt; //西面對應房間的格子數}if (s[i][j].n&&!s[i][j].y2){s[i][j].y2=cnt; //南面對應房間的格子數}if (s[i][j].b&&!s[i][j].y1){s[i][j].y1=cnt; //北面對應房間的格子數}}}} }void res(){ //求出結果 int p,q,m=0;char ch;for (int j=1;j<=c;j++){for (int i=r;i>0;i--){if (s[i][j].b){if (s[i][j].a!=s[i-1][j].a&&s[i][j].y1+s[i-1][j].y2>m){m=s[i][j].y1+s[i-1][j].y2;p=i;q=j;ch='N';}}if (s[i][j].d){if (s[i][j].a!=s[i][j+1].a&&s[i][j].x1+s[i][j+1].x2>m){m=s[i][j].x1+s[i][j+1].x2;p=i;q=j;ch='E';}}}}fout<<m<<endl<<p<<" "<<q<<" "<<ch<<endl; }int main() {init();m=0;sum=0;memset(f,false,sizeof(f));for (int i=1;i<=r;i++){for (int j=1;j<=c;j++){if (!f[i][j]){f[i][j]=true;cnt=1;dfs(i,j);m=max(m,cnt);sum++;cal(); }}}fout<<sum<<endl;fout<<m<<endl;res();return 0; }突然不是很懂以前的想法,說一下現在的吧!
1.房間數直接dfs即可,每一次從沒有到過的格子開始遍歷,遍歷的次數就是所有的房間數,每次統計當前房間格子的總數就能求出最大值了。
2.比較難的應該就是選擇墻來推翻了,首先我們得明確一下題意,優先選擇東邊的墻推翻,若有多個解,則選擇北邊的墻推翻。嗯,由于我們要計算房間數目,假設第cnt個房間就表示當前的房間號為cnt,每次的值加一,那么我們就可以用這個數來標記每一個格子屬于哪一個房間號,在遍歷房間cnt時所路過的格子都是屬于這個房間的,我們再保存一下每個房間包含的格子數,那么我們可以通過當前的格子得到房間號,通過房間號得到當前格子所在房間的總的格子數,這樣我們就得到了我們預處理的數據了。
3.接下來我們就要選擇墻了,某個墻的相鄰兩個房間的格子數相加就是推翻這個墻所獲得的格子數的總和,根據題意可得,我們應該從左到右,從下往上求得我們需要的結果。
還有一個需要注意的地方,我們可以根據當前的x[i][j]值直接得到它的周圍有沒有墻,dx,dy,與d都是一一對應的,由k得到當前要去往哪個方向,x[i][j]與d[k]相與就能得到k方向有沒有墻了。
總結
以上是生活随笔為你收集整理的USACO-Section2.1 The Castle (深度优先搜索)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: no crontab for root
- 下一篇: 基本数据类型float和double的区