HDU1045 Fire Net

http://acm.hdu.edu.cn/showproblem.php?pid=1045


解题思路:本题是加条件变形后的搜索题,中间有检查的成份,弄的题目有点恶心的感觉。


给定一个n*n的地图,图中有“。”和“X”,"X"表示墙,“。”表示空地。可以在空地上修建炮台,当时互相可见的炮台(同行或同列,且中间没有墙隔开)就会互相摧毁对方,造成事故。要求在图中的空地上修建炮台,要使炮台不会互相攻击。要求出最多能修建多少个炮台。地图的大小n<=4.虽然题目比较恶心,还好数据不大。


定义一个数组map,用于存储地图情况,开始的时候,全部初始化为-1,输入地图后,根据输入地图进行修改。空地用“0”表示,墙用“1”表示,炮台用“2”表示 。输入完毕后,开始搜索。

每次搜索都从地图的左上角一次搜索所有位置,若该位置是空地“0”,就要考虑能不能建炮台了。就要检索它的四个方向了,若是遇到炮台则改变标记变量,跳出。要是遇到边缘的“-1”或是墙“1”,直接跳出。四个方向检索完后,要使标记变量没有改变,则该处可以修建炮台,考虑要不要建炮台,深搜下一层即可。对于每一层的搜索,对其计数变量sum若sum>max,即当前搜索到的方案能建的炮台数是以前的方案修的炮台数里的最多的,则改变max的值为sum。深度优先搜索完成后,直接输出max即可。


9083371 2013-08-30 19:17:31 Accepted 1045 0MS 204K 1608 B G++ try it
#include<stdio.h> #include<string.h> int n,max;   //地图大小,最大值 int map[6][6]; int dir[4][2]= {1,0,0,1,-1,0,0,-1};  //四个检索方向 void dfs(int sum)    //深搜 {     int t,h;     if(sum>max)max=sum;  //当前能建炮台数最多     for(t=1; t<=n; t++)  //从地图的左上方一次搜索     {         for(h=1; h<=n; h++)         {             if(map[t][h]==0)  //若该处是空地,考虑能不能建炮台             {                 int flag=1;   //标记变量,看该地能不能建炮台                 for(int i=0; i<4; i++)   //检索四个方向                 {                     int xx=t;                     int yy=h;                     while(1)                     {                         xx=xx+dir[i][0];                         yy=yy+dir[i][1];                         if(map[xx][yy]==-1)break;  //遇到地图边缘,直接跳出                         else if(map[xx][yy]==1)break;  //遇到墙,直接跳出                         else if(map[xx][yy]==2)  //遇到炮台,该处不能建炮台,改变标记变量,跳出                         {                             flag=0;                             break;                         }                     }                 }                 if(flag)  //标记变量未边,就该点进行下一层深搜                 {                     map[t][h]=2;                     dfs(sum+1);                     map[t][h]=0;                 }              }         }     } } int main() {     int i,j;     char x[5];     while(scanf("%d",&n)&&n)     {         max=0;         memset(map,-1,sizeof(map));         for(i=1; i<=n; i++)         {             scanf("%s",x+1);             for(j=1; j<=n; j++)  //逐个位置处理             {                 if(x[j]=='.')map[i][j]=0;  //该位置为空地                 else map[i][j]=1;   //该位置为墙             }         }         dfs(0);   //深搜开始         printf("%d\n",max);     }     return 0; } 

后记:

  我会说这个题目我做了一年多了吗?我真不好意思说,做为一个ACMer,这个题目我做了一年多才A掉。其实题目不难,就是没有勇气。这个题目,老师挑过4次到专题了,就是一直没有勇气去做,想到要四面检索就觉得头皮发麻。什么叫自己吓自己。这就是自己吓自己,就是叫做没有勇气。其实题目并不难,就像一座高山一样,没有足够的勇气,攀不了顶,这个题目,没有足够的勇气就不会去打。我承认我是懦弱过,终于,还是敌不过时间,最终被时间逼得什么都不怕了。

        成为ACMer已经一年多了,马上就要大三的我,去年就已经参加过省赛。当时就是抱着打酱油的心去的,鄙人所在学校确实是ACM弱校,弱到要用大一的孩子来凑省赛的人数。不单只是学校学院不重视,学生对这方面的兴趣也不浓。能熬到现在,其实我已经很佩服自己了,也有很多人佩服我。ACMer确实是很苦的,机房,食堂,宿舍,三点一线。屌丝,电脑,近视眼是我们的特殊,虽然我不近视,但是,也只能说是一个例外。

        弱校是很期待有人能拼命的,期待有人能在一片荆棘中走出一条血路。第一个人有多苦,只有自己能明白。我校已经好几年没有在省赛中拿奖了,以前拿过的也是一些三等奖之类的,近两年,就连三等奖也没有了。不甘心啊,奋斗了这么久。别人在玩,我在代码,别人在家,我在机房代码,别人在旅游,我在机房代码。这么久了,马上进去职业奋斗阶段了,大学最能玩的两年飘过了,我怎么甘心就这样离开。来过这里,呆了这么久,好歹也该留个印记啊,不说雕像什么的,只是也要留个名啊。希望我们今年能斩开荆棘,结束JSU的这段光头的历史。

        ACM是很残酷的,输掉了技术,就会连尊严都输掉。我亲身见证那种感觉,那个历史。应邀的团队,只有几个打酱油的人参加我们的邀请赛,不觉得这就是鄙视吗?赤裸裸的鄙视!就因为是弱队,别人打酱油的都能虐到你,别人不屑出赛队。

        记得以前看过一篇ACM弱校血泪史,那真的是拼命。“30天,90包泡面,40包咸菜”。任何一个学校的荣誉都不是生来就有的,都是前辈拼出来的,若是自己前面没有这样的前辈,就让自己成为学弟学妹的那个前辈吧。

        去年,看到即将大三的学长晚上坚持来机房,很是不解。他们是不愿平庸啊!不远走过了,脚印都没有。后面其中之一被尊称“h神”,为何成神,修练成仙啊!现在自己也是即将大三的了,才能略体会到他们的感觉,再不拼搏,就没有机会了。我知道,大一也有部明白我的人,我相信等到他们到了这个时候,也许就懂了。

       其实,所谓的勇气,不一定是天生就有的。我做这个题的勇气是活生生被逼出来的。队里分到我搞搜索,去年最怕的搜索啊。其实学搜索的勇气也是被逼出的。去年的队友抛弃,原因之一是基本算法都不会。当时我分到的任务不是贪心等基本算法吗?不是有人搞搜索吗?我不会搜索也是依赖的吧。既然没有可以依赖了,就自己上,他们能学,我也能学。眼带泪水对着别人的代码打了将近一周后,我终于可以做基本的搜索题了。都是被逼的啊!

       做为即将参加第二次省赛的ACMer,连这么基础的搜索题都没有A过,无颜面对啊。始终还是逼出来了。狠下心来,逼着自己必须A过,硬着头皮打完,带着恶心调好,终于过了。多补容易啊。ACMer冲得什么啊?不就是这种AC后的感觉吗?其实ACM不一定能给你辉煌,也不一定能给你好的工作和未来,她就像毒药,让人一旦陷入,就无法自拔。

        真心希望今年不要再空手过来,老师的目标也许是高了,只能说,必须尽力,只要不空手而归,我们就已经成功了,已近是功成了,至少,不再无颜说自己是ACMer了。

         ACM弱校,让我们来,至少要尽全力。