JOJ 1017(深度优先搜索)

【原题链接】

http://[2001:da8:b000:6221:213:72ff:fe8f:5269]/joj/showproblem.php?pid=1017 (为ipv6地址)

【题目大意】

假设我们有一个有直线街道的方形城市。城市的地图是由N列和N行构成的方形平面,每条表示一条街道或一段墙。
   一个碉堡有四个开口用于射击。这四个开口分别面向北、东、南和西。每个开口都有一个挺机枪。假设子弹的威力很大,可以穿越任何距离而且可以破坏掉线上的碉堡。另一方面墙是非常结实的,可以
挡住子弹。
   目标是在城市中尽可能多的放置碉堡而互不摧毁。碉堡的布局规定是在地图的水平线或垂直列上没有两个碉堡,除非他们中间有墙隔开。在这个问题上我们会考虑有墙的方形小城市(最多4*4)

   你的任务是写一个程序,给出地图的描述,计算出城市中合规定地放置的最大碉堡数目。输入包括一张或多张地图描述,跟着一行以0结束输入。每张地图描述开始以N作为一行,N是城市的大小。N最多是4。接下来的N行每行描述地图中的一行,以一个‘.’象征一个空地,以大写字母‘X’象征一堵墙。在输入过程中没空格。
   每组测试输出一行一个数,即城市中按规定放置的最大碉堡数。

【解题思路】

         深度优先搜索,枚举所有情况,找到最优解,详见代码。

【备注】

         此题为深搜的简单题,若对递归和深搜原理理解不深acmer可研究下此题,注意递归的出口,防止递归进入死循环造成栈溢出。

【源程序】

[code]

#include <iostream>

using namespace std;

 

char map[5][5];

int size,ans;

 

bool canPut(int x, int y)

{//此函数检验该处是否可放

         int i;

         if(map[x][y]=='X') return 0;

         if(map[x][y]=='#') return 0;

         for(i=x;i>=0;i--)

         {

                   if(map[i][y]=='X') break;

                   if(map[i][y]=='#') return 0;

         }

         for(i=x+1;i<size ;i++)

         {

                   if(map[i][y]=='X') break;

                   if(map[i][y]=='#') return 0;

         }

         for(i=y;i>=0;i--)

         {

                   if(map[x][i]=='X') break;

                   if(map[x][i]=='#') return 0;

         }

         for(i=y;i<size;i++)

         {

                   if(map[x][i]=='X') break;

                   if(map[x][i]=='#') return 0;

         }

         return 1;

}

 

bool allPut()

{//此函数检验此图是否有处可放

         int i,j;

         for(i=0;i<size;i++)

         {

                   for(j=0;j<size;j++) if(canPut(i,j)) break;

                   if(j<size) return 0;

         }

         return 1;

}

 

void dfs(int num)//num表示已放的碉堡数

{

         int i,j;

         if(allPut()) { ans=ans>num?ans:num; return; }

         //如果已经无地可放,记录此时放入的碉堡数并更新结果,返回上一层

         for(i=0;i<size;i++) for(j=0;j<size;j++)

         {

                   if(!canPut(i,j)) continue;//如果此处不可放 看下处

                   map[i][j]='#';//此处放碉堡

                   dfs(num+1);//递归到下层检验是否可再放

                   map[i][j]='.';//下层不可再放,将此处碉堡清空,看另一个分支

         }

}

 

int main()

{

         int i,j;

         while(cin>>size,size)//图大小,遇0结束

         {

                   for(i=0;i<size;i++) for(j=0;j<size;j++) cin>>map[i][j];

                   //输入图

                   ans=0;

                   dfs(0);//深度优先搜索

                   cout<<ans<<endl;//输出结果

         }

         return 0;

}

[/code]

你可能感兴趣的:(搜索)