hdu 1171 Big Event in HDU

来源:互联网 发布:淘宝小卖家 编辑:程序博客网 时间:2024/05/29 15:10

题目

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

分析

首先分析题目之后给我的第一感觉就是一个多重背包的问题,我首先用多重背包的思路写了一个提交TLE,然后我想当然的意识到可能需要单调队列优化将时间复杂度降到O(NV)。然后,我用单调队列优化又写了一个提交之后发现仍然TLE,这下我就郁闷了一下午加上晚上两个小时,在网上找了一个正确的经行比较,发现运来是在判断N的时候,将N!=-1写在while循环中了,修改之后提交马上AC,然后又将之前多重背包的按个提交仍然AC。

此时更郁闷了,我在本地测试正确,为什么HDU提交就TLE呢?求大神赐教!!!

复杂度

单调队列优化之后时间复杂度为O(NV);

涉及内容

算法:动态规划

数据结构:单调队列

感想

当思路没有错的时候,题目任然出错:1.讲代码思路梳理清楚;2.将不规范的写法书写规范再分析;3.可能和系统平台有关(例如此处,不能这样写while(scanf("%ld",&N),N!=-1) ;还有杭电系统为windows,六十四位用__int64);

代码

#include <stdio.h>#include <stdlib.h>#include <string.h>#define max1171(a,b) (a>b?a:b)long V1171=0;long f1171[125001],head=0,rear=0;int v1171[51],m1171[51];long a[5001],b[5001];void insert1171(long x,long y){while(head<=rear && y>=f1171[rear]) --rear;a[++rear]=x,b[rear]=y;}int main(){freopen("in.txt","r",stdin);long N,max=0,temp=0;while(scanf("%ld",&N)) {if(N<0) break;//此处悲催了一个下午,不能放到while循环中memset(f1171,0,sizeof(f1171)),V1171=0,max=0;for(int i=1;i<=N;++i) {scanf("%d %d",&v1171[i],&m1171[i]);V1171+=v1171[i]*m1171[i];}temp=V1171,V1171/=2;for(int i=1;i<=N;++i){for(long j=0;j<v1171[i];++j)//余数{head=1,rear=0;for(long k=0;k<=(V1171-j)/v1171[i];++k)//个数{insert1171(k,f1171[k*v1171[i]+j]-k*v1171[i]);while (head<=rear && k-a[head]>m1171[i]) ++head; //因为每类有m1171[i]个,所以最多从k-m1171[i]出跳转,这就是单调对垒长度的限制f1171[k*v1171[i]+j]=b[head]+k*v1171[i];}}}for(long i=1;i<=V1171;++i)max=max1171(f1171[i],max);printf("%ld %ld\n",temp-f1171[V1171],f1171[V1171]);}return 0;}
然后给出依然正确的多重背包的解题代码供大家参考:

//TLE---在HDU中第一次是因为不能将N与-1的比较放到括号中#include <stdio.h>#include <stdlib.h>#include <string.h>#define max1171(a,b) (a>b?a:b)long V1171=0;long f1171[125001];long v1171[125001],m1171[125001];void ZeroOnePack1171(long w,long c){for(long i=V1171;i>=w;--i)f1171[i]=max1171(f1171[i],f1171[i-w]+c);}void CompletePack1171(long w,long c){for(long i=w;i<=V1171;++i)f1171[i]=max1171(f1171[i],f1171[i-w]+c);}void MutilPack1171(long w,long c,long p){if(w*p>=V1171) {CompletePack1171(w,c);return;}int k=1;while(k<p) {ZeroOnePack1171(w*k,c*k);p-=k;k+=k;}ZeroOnePack1171(w*p,c*p);}int main(){freopen("in.txt","r",stdin);long N,max=0,temp=0;while(scanf("%ld",&N)) {if(N<0) break;memset(f1171,0,sizeof(f1171)),V1171=0,max=0;for(int i=1;i<=N;++i) {scanf("%d %d",&v1171[i],&m1171[i]);V1171+=v1171[i]*m1171[i];}temp=V1171,V1171/=2;for(int i=1;i<=N;++i)MutilPack1171(v1171[i],v1171[i],m1171[i]);for(long i=1;i<=V1171;++i)max=max1171(f1171[i],max);printf("%ld %ld\n",temp-max,max);}return 0;}

参考文献


1.http://hi.baidu.com/sy2006ppkdc/item/287eb50a8e2544833c42e217(给出单调队列优化的框架)

2.http://www.cnblogs.com/shenshuyang/archive/2012/08/17/2643586.html(另外一种解题思路,值得参考)

3.http://blog.csdn.net/qiusuo800/article/details/8820905(本人写的单调队列优化思路,供大家学习大笑)