usaco4.1.2 有N块长木板,希望得到M块短木板,问最多可以裁多少块短木板

来源:互联网 发布:网络信息安全工作方案 编辑:程序博客网 时间:2024/04/30 13:36

        题意:给出N块长木板的长度,现在需要M块短木板,每块短木板的长度也给出,问最多可以裁多少块所需的短木板?

        分析:刚开始想贪心,DP什么的未果,就只能搜索了。想了很多种方法,很多剪枝。终于把它给过了

                  (1)枚举得到短木板的块数比暴搜要快很多,因为找到了一种情况就可以直接退出

                  (2)最后得到的短木板,一定是所需短木板中最短的那几块         

                  (3)对于每个长木板来说,裁的短木板从长到短试要好些

                  (4)对于每个长木板,裁同一长度的短木板时,只关心数量,具体哪一块是无关紧要的

                  (5)如果现在长木板正好能裁成当前短木板的整数倍,那么就直接裁了,不用试裁更短的短木板了

                  (6)最关键的剪枝:对于每种情况都有可以浪费的最大长度,如果到目前为止浪费的比它还多的话,后面就没有搜的必要了

/*ID:kgdpgfy1LANG:C++PROG:fence8*/#include<stdio.h>#include<string.h>#include<iostream>#include<algorithm>using namespace std;int a[55],num[130],num1,n,sum,sum1,mx,r,mn;bool flag;int Min(int a,int b){return a<b? a:b;}//现在试下标为index的原始的长木板,试到now的小木板,长木板还有left长,前面已裁好sum块小木板,总共需要need块小木板,允许浪费的最大长度为wastebool DFS(int index,int now,int left,int sum,int need,int waste){if(flag||sum==need)//找到符合的情况就跳出{flag=true;return true;}if(waste<0) return false;//浪费的比允许的最大浪费量还多if(index==n)return false;if(now<=0||left==0)//下一根长木板return DFS(index+1,mn,a[index+1],sum,need,waste-left);int i;for(i=Min(left/now,num[now]);i>=0;i--)//短木板从多到少枚举{num[now]-=i;DFS(index,now-1,left-now*i,sum+i,need,waste);num[now]+=i;if(flag) return true;//如果有满足的if(left-now*i==0) break;//如果正好不剩的话,那么是最优的,其它的就不用试了}return flag;}int main(){freopen("fence8.in","r",stdin);freopen("fence8.out","w+",stdout);int i,j,k;while(scanf("%d",&n)!=EOF){sum=0;for(i=0;i<n;i++){scanf("%d",&a[i]);sum+=a[i];}memset(num,0,sizeof(num));scanf("%d",&r);for(i=0;i<r;i++){scanf("%d",&j);num[j]++;}for(num1=0,sum1=0,mn=1;mn<=128;mn++){k=num[mn];for(j=1;j<=k;j++)//枚举短木板块数{num1++;num[mn]=j;sum1+=mn;flag=false;if(!DFS(0,mn,a[0],0,num1,sum-sum1))break;}if(j<=k) break;}if(!flag) printf("%d\n",num1-1);//是break出来的else printf("%d\n",r);//小木板全部都能弄到}return 0;}


 

                                 

 

      

原创粉丝点击