zoukankan      html  css  js  c++  java
  • 【POJ1011】Sticks-DFS+调整法剪枝

    测试地址:Sticks

    题目大意:有n根小棍,要拼成若干根长度相等的大棍,问大棍的最小长度是多少。

    做法:很容易确定搜索思路:枚举大棍的长度,然后进行DFS查看是否可行,用一个bool函数dfs(r,l)表示当前剩余r根小棍未使用,当前大棍剩余长度为l的情况下是否有解。但是单纯这样裸搜,不知道要搜多少年呢...于是在看了一些资料之后,找到了一些剪枝思路:

    1.如果当前大棍长度不是小棍长度之和的因数,不用考虑(应该是很容易就能想到的剪枝)。

    2.大棍长度不会小于最长小棍的长度,并且如果在大棍长度≤小棍长度之和/2的范围中如果无解,则结果就已经可以确定为小棍的长度之和(即将所有小棍拼成一根大棍),所以枚举范围为:最长小棍长度≤大棍长度≤小棍长度之和/2。

    3.如果将小棍按长度由大到小排序,搜索的时间会显著减少。

    4.在开始拼一根新的大棍时,要选还未被使用的最长的小棍作为最开始的小棍,如果发现以这根小棍开始不能拼成这样的大棍,则直接退回去调整上一根大棍。

    5.用used数组来表示小棍使用过与否,如果在从小棍标号从小到大枚举的过程中,发现现在的小棍长度和上一根小棍长度相等,且上一根小棍没被使用,则判定为无解,因为如果有解则一定已经在搜索前一根小棍时就出解了。

    6.为预防重复搜索,应记录最近拼接的小棍编号no,只用枚举编号比no大的即可(如果是开始拼接一根新的大棍,参照剪枝4)。

    7.如果剩余长度等于当前所枚举的小棍长度,则说明该小棍正好填满这根大棍,但如果继续搜索后返回的结果是无解,则退回枚举上一根小棍。

    以下是本人代码:

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    int n,len[65],tot,no,i;
    bool used[65];
    
    bool cmp(int a,int b)
    {
      return a>b;
    }
    
    bool dfs(int r,int l)
    {
      if (r==0&&l==0) return 1;
      if (l==0) l=i;
      int start=1;
      if (l!=i) start=no+1; //剪枝6
      for(int j=start;j<=n;j++)
        if (!used[j]&&len[j]<=l)
    	{
    	  if (j>1&&!used[j-1]&&len[j-1]==len[j]) continue; //剪枝5
    	  used[j]=1;no=j;
    	  if (dfs(r-1,l-len[j])) return 1;
    	  used[j]=0;
    	  if (len[j]==l||l==i) return 0; //剪枝4,7
    	}
      return 0;
    }
    
    int main()
    {
      while(scanf("%d",&n)&&n)
      {
        tot=0;
    	for(i=1;i<=n;i++)
    	{
    	  scanf("%d",&len[i]);
    	  tot+=len[i];
    	}
    	sort(len+1,len+n+1,cmp); //剪枝3
    	for(i=len[1];i<=tot/2;i++) //剪枝2
    	  if (!(tot%i)) //剪枝1
    	  {
    	    memset(used,0,sizeof(used));
    		no=1;
    		if (dfs(n,i))
    		{
    		  printf("%d
    ",i);
    		  break;
    		}
    	  }
    	if (i>tot/2) printf("%d
    ",tot);
      }
      
      return 0;
    }
    


  • 相关阅读:
    linux 添加secondary ip
    最大传输单元(MTU)
    【PSY】 [歌詞] 父親
    make clean与make distclean的区别
    flex就是b/s中的c/s,要装插件flash player
    as中的replace只写了一个参数
    6个简单的解决方案解决Internet Explorer中的透明度问题
    9个优秀网上免费标签云生成工具
    2012年网页设计趋势
    11个非常漂亮动物为主题的高品质图标集
  • 原文地址:https://www.cnblogs.com/Maxwei-wzj/p/9793902.html
Copyright © 2011-2022 走看看