题目链接:http://poj.org/problem?id=2063

  今天果然是卡题的一天。白天被hdu那道01背包的变形卡到现在还没想通就不说了,然后晚上又被这道有个不大也不小的坑的完全背包卡了好久。这题主要是说让你选择不同的债券(每种债券的费用和年利率的属性),然后n年后使得本金最大,如果仅仅是问一年的话就是个裸完全背包的题了,不过它是n年,每年得到的总利息都会加入到本金中变为下一年的本金,知道了这个后就很好处理了,在这道题里每年变化的本金就是背包容量,然后债券那两个属性就是物品的费用(or体积)和价值(or重量)。

  一开始我快速码好后提交结果各种MLE,TLE,当注意到每种债券的费用都是1000的倍数时我改了下,大概主函数如下:

 while(y--){
memset(dp,,sizeof(dp));
for(i=; i<=d; ++i)
for(j=cost[i]; j<=capital; j+=)
dp[j]= max(dp[j],dp[j-cost[i]]+value[i]);
capital+= dp[capital/*];
}

  提交后还是TLE,我就奇怪了,虽说和标程的常规方法不同,但初步分析下复杂度应该是一样的啊,j 每次都是1000地递增的,后来经过用标程提交几番痛苦的摸索后终于知道TLE的根本原因是memset函数!因为我的dp数组开到了 int dp[7000006] 这么大,而y的上限是40,相乘后就是280000000,1s根本没法承受!本作为辅助的步奏却大大超过了主算法的时间,所以我干脆用for手动清零算了,改成这样:

 //    memset(dp,0,sizeof(dp));
for(j=; j<=capital; j+=)
dp[j]= ;

  然后华丽地RE了,看来数组dp[7000006]竟然还不够大,然后我稍微开大了一点点,就MLE了,看来这个是30000KB的临界值了(后来我才发现这题的本金即背包容量会达到 5kw!即使数组勉勉强强开得下,也绝对远远超过了大多数题目的内存限制),没办法了,即使我这种方法的技巧性再强,还是会被各种TLE,MLE,RE卡死,看来真的需要常常规规的去做了。需要把债券的费用和本金缩小1000倍,这样子背包容量的 j 循环就可以连续的了,数组的空利用率也大大提交(T.T 和我上面的做法相比就可以看出来)。这样做的话maxn只需要开到50000即可,实际放大后就是5kw,如果硬要把maxn开到百万级别以上的话,memset就不能用,必须手动清零,否则时间就会浪费在为数组那些实际上不会用上的空间进行清零,即使memset按字节来处理也忍受不了千万级别的1s时限,基于各种修改过后的代码如下:

 #include<cstdio>
#include<cstring>
#include<algorithm>
#include<ctime>
using namespace std;
const int maxn= ; int dp[maxn+], cost[],value[]; int main(){
int t,capital,y,d,i,j,tmp;
scanf("%d",&t);
while(t--){
scanf("%d%d%d",&capital,&y,&d);
for(i=; i<=d; cost[i]/= , ++i)
scanf("%d%d",cost+i,value+i);
double b = clock();
while(y--){
// memset(dp,0,sizeof(dp)); 这个没有错,但上面的 maxn一定不能太大!
tmp= capital/;
for(j=; j<=tmp; ++j)
dp[j]= ;
for(i=; i<=d; ++i)
for(j=cost[i]; j<=tmp; ++j)
dp[j]= max(dp[j],dp[j-cost[i]]+value[i]);
capital+= dp[tmp];
}
double c = clock();
// printf("%.f\n",c-b);
printf("%d\n",capital);
}
return ;
}

  交之,63ms Accepted。

  从这道题中我得到的教训就是为了不用推倒重来而使用上那一点点小技巧(即j+=1000),却使数组空间大大浪费掉(不是么,1/1000的利用率 T.T),然后还带来了MLE or RE的不可避免的风险;第二个学到的就是,memset函数也有可能是TLE的根源,要看清数组会有多大,所以以后当TLE时检查了scanf里有没漏 & 取址符或long long的读入有误,或者少了个EOF,或者其他等等等等非算法问题造成的超时后,不妨看看是否有可能数组太大,memset会不会做了多余的工作(为数组实际用不上的空间进行操作)等等。

POJ 2063 Investment 完全背包的更多相关文章

  1. POJ 2063 Investment (完全背包)

    A - Investment Time Limit:1000MS     Memory Limit:30000KB     64bit IO Format:%I64d & %I64u Subm ...

  2. POJ 2063 Investment 滚动数组+完全背包

    题目链接: http://poj.org/problem?id=2063 题意: 你现在有现金m元,你要做n年的存款投资,给你k种投资方式,每种需要现金vi元,能获得xi元的理论,一年到期后你要利用拿 ...

  3. poj 2063 Investment ( zoj 2224 Investment ) 完全背包

    传送门: POJ:http://poj.org/problem?id=2063 ZOJ:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problem ...

  4. poj 2063 Investmen 完全背包

    这个题的想法不难,两个点: 1 是完全背包 2 是考虑/1000,降低复杂度   但是提交的时候反复的wa,最后找问题原来是dp开小了,可是dp本来开1005,后来开到100030过了.哎,如果没有时 ...

  5. [POJ 2063] Investment (动态规划)

    题目链接:http://poj.org/problem?id=2063 题意:银行每年提供d种债券,每种债券需要付出p[i]块钱,然后一年的收入是v[i],到期后我们把本金+收入取出来作为下一年度本金 ...

  6. poj 2063 Investment

    题意:给定一个初始资金capital,然后给定d种投资方案,每种投资方案中有投资额value[i](是1000的倍数)和利息interest[i],每年的投资就可以拿到全部利息,然后累加起来继续投资利 ...

  7. 专题复习--背包问题+例题(HDU 2602 、POJ 2063、 POJ 1787、 UVA 674 、UVA 147)

    *注 虽然没什么人看我的博客但我还是要认认真真写给自己看 背包问题应用场景给定 n 种物品和一个背包.物品 i 的重量是 w i ,其价值为 v i ,背包的容量为C.应该如何选择装入背包中的物品,使 ...

  8. poj 2063完全背包

    题意:给出总资金和投资年份 ,n个股票 给出股票价格和其一年的利润.问如何选择能获得最大利润. 思路:股票可以重复选择,完全背包问题,完全背包也是从01背包衍生而行的,其主要区别在于中间那层循环的次序 ...

  9. POJ 1155 (树形DP+背包+优化)

    题目链接: http://poj.org/problem?id=1155 题目大意:电视台转播节目.对于每个根,其子结点可能是用户,也可能是中转站.但是用户肯定是叶子结点.传到中转站或是用户都要花钱, ...

随机推荐

  1. Human Gene Functions

    Human Gene Functions Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 18053 Accepted: 1004 ...

  2. Flip Game 分类: POJ 2015-06-15 14:59 22人阅读 评论(0) 收藏

    Flip Game Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 33519   Accepted: 14642 Descr ...

  3. JAVA基础知识之IO——IO流(Stream)的概念

    Java IO 流 Java将不同的设备或载体(键盘.文件.网络.管道等)的输入输出数据统称为"流"(Stream),即JAVA的IO都是基于流的. JAVA传统的所有流类型类都包 ...

  4. 通过PowerShell查询本机IP地址

    脚本内容如下: Write-Host "本机IP地址为:"(ipconfig|findstr "IPv4")[1].split(":")[1 ...

  5. 如何通过Button获取UITableViewCell

    发现一个奇怪的问题: 手机(ios7) 2015-06-17 15:11:29.323 ***[1412:60b]  [btn superview] =  UITableViewCellContent ...

  6. 如何在安装32位Oracle客户端组件的情况下以64位模式运行

    C#使用System.Data.OracleClient连接Oracle数据库.之前在WinXP上正常运行的程序移植到Windows 2008 x64上之后就连不上数据库了,错误信息如下:启动data ...

  7. qt 1 qt开发中的窗口设计

    一个简单的qt界面 相应代码如下: setWindowTitle(tr("Sotware"));//设置窗体标题 ui->tabWidget->removeTab(); ...

  8. JAVA 实战练习

    1.判断变量是否为奇数偶数. package com.JAVA; import java.util.Scanner; public class text { public static void ma ...

  9. CNV

    CNV: 人类主要是二倍体.如果有些区域出现3个.4个拷贝,那就是扩增了,如果只出现1个拷贝,就是缺失.所以CNV分析是依靠特定位置的测序深度来估算的,先在染色体上划窗,然后看每个窗口的平均测序深度, ...

  10. HUD 2203 亲和串

    HUD 2203 亲和串 Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 32768/32768K (Java/Others) [题目描述 - ...