[DFS]HDU1518

来源:互联网 发布:蜂群算法 编辑:程序博客网 时间:2024/05/24 06:01

传送门

题意就是好多棍子,看能不能拼成正方形。主要注意的有几点:
  • 所有棍子都要用到,不能剩余
  • 输入已经保证大于4根棍子了。所以无需判断可能小于3根棍子的情况
  • 棍长的总数首先要是4的倍数,才能进行。否则直接输出 “no”
  • 当前面前提满足以后,再满足3 根棍子拼好,就完工了。最后一根一定能拼好。
解法就是DFS——->深度优先搜索。DFS的思路就是一个图沿着一条路走下去,当走不下去的时候就回溯到上一结点再去走没有走过的岔路。
换算成数据结构的话,就要有一个“标记”来标记每个结点是否走过。DFS具体的实现方式,常见的一种就是:循环里面嵌套递归,这也算是一个DFS的框架。而剩下的要补充的“题眼”(也就是关键的地方)是要转移的状态
[cpp] view plain copy
print?在CODE上查看代码片派生到我的代码片
  1. bool dfs(int count,int pos,int res)  
这是本题中DFS算法的状态。三个要素 count (已经拼好的棍子个数),pos (现在遍历的第几根棍子),res (要凑成目标长度剩余的长度)
当然在输入数据以后要进行一次排序,从大到小排好依次遍历。
我们要定义一个全局的变量 goal 代表你要凑齐的目标长度,换句话说就是总长度的 1/4 。
[cpp] view plain copy
print?在CODE上查看代码片派生到我的代码片
  1. goal = sum/4;  
标记的数组我们定义为used[21].值为 true 则标记过,即用过了。值为 false 则未用过。
[cpp] view plain copy
print?在CODE上查看代码片派生到我的代码片
  1. //声明,全局  
  2. bool used[21];  
  3. //初始化为false,main函数中  
  4. memset(used,false,sizeof(used));  
下面看DFS函数的代码:
[cpp] view plain copy
print?在CODE上查看代码片派生到我的代码片
  1. bool dfs(int count,int pos,int res)  
  2. {  
  3.     if(count==3)//3根拼好就能保证都拼好  
  4.         return true;  
  5.     for(int i=pos;i<t;i++)//DFS框架循环  
  6.     {  
  7.         if(used[i])//1  
  8.             continue;  
  9.         used[i] = true;//2  
  10.         if(stick[i]==res)//3  
  11.         {//DFS框架中的递归  
  12.   
  13.             if(dfs(count+1,0,goal))//4  
  14.                 return true;  
  15.         }  
  16.         else if(stick[i]<res)//5  
  17.         {//DFS框架中的递归  
  18.             if(dfs(count,i+1,res-stick[i]))//6  
  19.                 return true;  
  20.         }  
  21.         used[i] = false;//7  
  22.     }  
  23.     return false;  
  24. }  
//1:如果标记过就跳过下面过程
//2:先标记好true
//3:如果第i根棍子的长度和你剩余的所需要的棍子的长度一样。那么这根棍子就拼好了
//4:由//3可知,又拼好了一根,所以递归下一个棍子要拼的状态,count+1。而pos初始化为0.从头开始遍历,res变为goal,即下一根棍子剩余的长度是全部所需长度。
//5:如果第i根棍子的长度小于目前所需的。那么也把它加上
//6:下一个状态。count不变,因为这根还没拼好。pos = i+1,因为第i根已用。res-stick[i] 不言而喻了。
//7:前面如果满足的话,就会返回true。而不执行这一句//7这句。如果能走到//7这句,那么就是说前面的情况都不成功,也就是说这根棍子不能凑近去,所以要推翻加入这根棍子的方案

完整代码:
[cpp] view plain copy
print?在CODE上查看代码片派生到我的代码片
  1. #include <iostream>  
  2. #include <algorithm>  
  3. using namespace std;  
  4. bool used[21];  
  5. int stick[21];  
  6. int t,goal;  
  7. bool cmp(int a,int b)  
  8. {  
  9.     return a>b;  
  10. }  
  11. bool dfs(int count,int pos,int res)  
  12. {  
  13.     if(count==3)//3根拼好就能保证都拼好  
  14.         return true;  
  15.     for(int i=pos;i<t;i++)//DFS框架循环  
  16.     {  
  17.         if(used[i])  
  18.             continue;  
  19.         used[i] = true;  
  20.         if(stick[i]==res)  
  21.         {  
  22.             if(dfs(count+1,0,goal))//DFS框架中的递归  
  23.                 return true;  
  24.         }  
  25.         else if(stick[i]<res)  
  26.         {  
  27.             if(dfs(count,i+1,res-stick[i]))//DFS框架中的递归  
  28.                 return true;  
  29.         }  
  30.         used[i] = false;  
  31.     }  
  32.     return false;  
  33. }  
  34. int main()  
  35. {  
  36.     int n;  
  37.     cin>>n;  
  38.     while(n–)  
  39.     {  
  40.         cin>>t;  
  41.         int sum=0;  
  42.         for(int i=0;i<t;i++)  
  43.         {  
  44.             cin>>stick[i];  
  45.             sum+=stick[i];  
  46.         }  
  47.         if(sum%4)  
  48.         {  
  49.             printf(”no\n”);  
  50.             continue;  
  51.         }  
  52.         goal = sum/4;  
  53.         memset(used,false,sizeof(used));  
  54.         sort(stick,stick+t,cmp);  
  55.         if(dfs(0,0,goal))//初始态  
  56.             printf(”yes\n”);  
  57.         else  
  58.             printf(”no\n”);  
  59.     }  
  60.     return 0;  
  61. }  

0 0
原创粉丝点击