hdu和poj的基础dp30道
题目转自:https://crazyac.wordpress.com/dp%E4%B8%93%E8%BE%91/
1.hdu 1864 最大报销额
唔,用网上的算法连自己的数据都没过,hdu的数据居然就过了。。垃圾数据。。
比如这个:100.00 3
1 A:1000.00
1 A:200.50
1 A:100.00
输出应该是100.00,然而网上的算法输出是200.50。。hdu的discuss区也是一片骂声。。看到有人说测试数据都是两位小数的(但题目没说),那就每个数据都乘100然后用01背包做吧。。。虽然显然慢了很多。。但实在忍不了网上的错误算法。。。
#include<iostream> #include<cstdio> #include<cmath> #include<cstring> #include<algorithm> #include<vector> using namespace std;vector<double> fp; int dp[3000005],Q;void ZeroOnePack(int w) {for(int i=Q;i-w>=0;i--)dp[i]=max(dp[i],dp[i-w]+w); }int main() {double q;int n;while(~scanf("%lf%d",&q,&n)){if(n==0) break;Q=q*100;fp.clear();for(int i=0;i<n;i++){int m;char lx,mh;double p,a=0,b=0,c=0;bool flag=1;scanf("%d",&m);for(int j=0;j<m;j++){cin>>lx>>mh;scanf("%lf",&p);if(lx=='A') a+=p;else if(lx=='B') b+=p;else if(lx=='C') c+=p;else flag=0;}if(a<=600&&b<=600&&c<=600&&a+b+c<=1000&&flag)fp.push_back((a+b+c)*100);}int len=fp.size();memset(dp,0,sizeof(dp));for(int i=0;i<len;i++)ZeroOnePack(fp[i]);double ans=dp[Q]/100.0;printf("%.2lf\n",ans);}return 0; }
2.hdu 1203 I Need A Offer
嘛,概率论。。求“得到至少一份offer的最大概率”==“一份offer都没得到的最小概率”
还是01背包,背包总量为n,每份offer对应cost值和percentage值,因为要算没得到offer的最小概率,所以保存概率的时候,保存1-percentage,dp[i]=min(dp[i],dp[i-cost]*percent),最后结果为(double)100-(dp[n]*100)%
#include<iostream> #include<cstdio> #include<cstring> using namespace std;struct sc {int cost;double per; }a[10005]; int n,m; double dp[10005];void zopack() {for(int i=0;i<=n;i++)dp[i]=1;for(int k=0;k<m;k++){for(int i=n;i-a[k].cost>=0;i--){if(dp[i-a[k].cost]*a[k].per<dp[i])dp[i]=dp[i-a[k].cost]*a[k].per;}} }int main() {while(scanf("%d%d",&n,&m)&&n+m){double percent;for(int i=0;i<m;i++){scanf("%d%lf",&a[i].cost,&percent);a[i].per=1.0-percent;}zopack();double ans=(1.0-dp[n])*100;printf("%.1lf%%\n",ans);}return 0; }
3.hdu 2955 Robberies
小偷要抢n个银行,当总逃走失败概率低于p时,成功逃走,依次输入在第i个银行要抢mi元,逃走失败概率为pi,问最多能抢走多少钱?
那么只要看抢了x个银行,成功概率大于1-p即可。
还是01背包,但是要注意:这道题,weight价值是成功概率1-pi,银行被抢的总值sum作为背包容量,cost花费是mi,然后根据01背包的dp值表格,我们知道i越接近sum,dp值越大,那么从sum开始i--进行遍历,找到第一个dp[i]大于等于总成功概率1-p的,此时的i就是最多能抢走的钱数。
//关于dp数组的初始化:由于要取max值,所以全部初始化为0,又因为dp[0]表示一个银行都没抢,此时的成功逃跑概率为1,故dp[0]=1
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std;double dp[10005]; int main() {int t;scanf("%d",&t);while(t--){double p,per[105];int n,cost[105],sum=0;scanf("%lf %d",&p,&n);p=1.0-p;for(int i=0;i<n;i++){scanf("%d %lf",&cost[i],&per[i]);sum+=cost[i];per[i]=1.0-per[i];}for(int i=0;i<=sum;i++)dp[i]=0.0;dp[0]=1.0;//一个银行都不抢 成功逃走的概率为1for(int k=0;k<n;k++)for(int i=sum;i-cost[k]>=0;i--)dp[i]=max(dp[i],dp[i-cost[k]]*per[k]);int i;for(i=sum;i>=0;i--)if(dp[i]>=p) break;printf("%d\n",i);}return 0; }
4.poj 2063 Investment
买基金。。最开始有本金sum,可供购买的基金有d种,打算买y年,每年结束本金会改变,此时可以更改购买方案。按照每年来看的话,其实就是完全背包,背包容量为sum,且容量sum每年都需更新,背包里有d种物品,第i件物品费用为购买价,价值为利润。
由于每种基金的购买价都是1000的倍数,利润不大于10%,本金最多1,000,000,最多买40年
至多可得到(1,000,000+((1+10%)^40))/1000=45259 所以dp数组开到46000
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std;struct node {int cost,weight; }a[15]; int dp[46000];int main() {int t;scanf("%d",&t);while(t--){int sum,year;scanf("%d %d",&sum,&year);int d;scanf("%d",&d);for(int i=0;i<d;i++){scanf("%d %d",&a[i].cost,&a[i].weight);a[i].cost/=1000;}int limit=sum;for(int y=0;y<year;y++){memset(dp,0,sizeof(dp));for(int k=0;k<d;k++)for(int i=a[k].cost;i<=limit/1000;i++)dp[i]=max(dp[i],dp[i-a[k].cost]+a[k].weight);limit+=dp[limit/1000];}printf("%d\n",limit);}return 0; }
5.poj 2392 Space Elevator
哈哈哈哈哈哈可以叫堆塔吗这题
有k种塔,分别给出每种塔的高度h和数目c,以及限制高度a(往上堆某种塔的时候不能超过它对应的a),问最多能堆多高?
这题用多重背包解,一开始把quantity看成quality还想说给我质量干嘛。。还打算用完全背包来着。。。
这题的数据得排下序,根据a的大小排升序,讲道理的话,a小的不就得先把它给堆了嘛。
重点!想当然的以为dp[最大的a]就是最大值了,其实不是啊。。所以还得遍历一遍dp来找最大值。。。不然就wa了
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> using namespace std;struct block {int h,a,c; }bl[405]; int dp[400005];void zop(int c,int w,int v) {for(int i=v;i>=c;i--)dp[i]=max(dp[i],dp[i-c]+w); }void cp(int c,int w,int v) {for(int i=c;i<=v;i++)dp[i]=max(dp[i],dp[i-c]+w); }void mp(int c,int w,int num,int v) {if(c*num>=v){cp(c,w,v);return ;}int k=1;while(k<num){zop(k*c,k*w,v);num-=k;k<<=1;}zop(num*c,num*w,v); }bool cmp(block x,block y) {return x.a<y.a; }int main() {int k;scanf("%d",&k);for(int i=0;i<k;i++)scanf("%d%d%d",&bl[i].h,&bl[i].a,&bl[i].c);sort(bl,bl+k,cmp);memset(dp,0,sizeof(dp));for(int i=0;i<k;i++)mp(bl[i].h,bl[i].h,bl[i].c,bl[i].a);int ans=0;for(int i=0;i<=bl[k-1].a;i++)ans=max(ans,dp[i]);printf("%d\n",ans);return 0; }
6.poj 1276 Cash Machine
道理跟上一题一样的,直接贴代码了,比上一题还简单,不用排序了,limit只有一个总的。
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> using namespace std; int cash,n,num[15],d[15],dp[100005];void zop(int c,int w) {for(int i=cash;i>=c;i--)dp[i]=max(dp[i],dp[i-c]+w); }void cp(int c,int w) {for(int i=c;i<=cash;i++)dp[i]=max(dp[i],dp[i-c]+w); }void mp(int c,int w,int num) {if(num*c>=cash){cp(c,w);return ;}int k=1;while(k<num){zop(k*c,k*w);num-=k;k<<=1;}zop(num*c,num*w); }int main() {while(~scanf("%d%d",&cash,&n)){for(int i=0;i<n;i++)scanf("%d%d",&num[i],&d[i]);memset(dp,0,sizeof(dp));for(int i=0;i<n;i++)mp(d[i],d[i],num[i]);int ans=0;for(int i=0;i<=cash;i++)ans=max(ans,dp[i]);printf("%d\n",ans);}return 0; }
7.hdu 2059 龟兔赛跑
作dp滚动的时候,开n+2的数组,从起点0到L一直往前滚,对于第i种([1,n+1])状态(从第一站到终点),遍历j 从[0,i)的状态,比较j站到i站之间的距离len与充满电最远行程c的大小,如果len大,就分两段(前c->vt1,后len-c->vt2)算时间,否则就全程len按速度vt1算时间,比较得出这j种状态(即直接从第j站到第i站,中间不停)中的最小值,即为dp[i]的值。
那么乌龟所用时间就是dp[n+1]啦,要用double存数据,和兔子所用时间L*1.0/vr比较。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std;int main() {int l;while(~scanf("%d",&l)){int n,c,t;int vr,vt1,vt2;int p[105];double dp[105];scanf("%d%d%d",&n,&c,&t);scanf("%d%d%d",&vr,&vt1,&vt2);for(int i=1;i<=n;i++)scanf("%d",&p[i]);p[0]=0;p[n+1]=l;dp[0]=0;double minn,temp;for(int i=1;i<=n+1;i++){minn=10e8;for(int j=0;j<i;j++){temp=dp[j];if(j) temp+=t;//充电需要时间,但第一次不用充电int len=p[i]-p[j];if(len>c)temp+=(len-c)*1.0/vt2+c*1.0/vt1;else temp+=len*1.0/vt1;minn=min(minn,temp);}dp[i]=minn;}if(dp[n+1]<l*1.0/vr)printf("What a pity rabbit!\n");else printf("Good job,rabbit!\n");}return 0; }
8.hdu 1059 Dividing
因为要判断能不能平分,所以sum如果为奇数就不行,否则,用多重背包(因为每种球都给了number数),容量v为sum的一半,然后看dp[v]是否等于另一半sum-v。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std;int dp[120005],v; void zop(int c,int w) {for(int i=v;i>=c;i--)dp[i]=max(dp[i],dp[i-c]+w); }void cp(int c,int w) {for(int i=c;i<=v;i++)dp[i]=max(dp[i],dp[i-c]+w); }void mp(int c,int w,int num) {if(c*num>=v){cp(c,w);return ;}int k=1;while(k<num){zop(k*c,k*w);num-=k;k<<=1;}zop(num*c,num*w); }int main() {int n[7];int cas=0;while(scanf("%d%d%d%d%d%d",&n[0],&n[1],&n[2],&n[3],&n[4],&n[5])&&n[0]+n[1]+n[2]+n[3]+n[4]+n[5]){cas++;int sum=0;for(int i=0;i<6;i++)sum+=(i+1)*n[i];if(sum%2==1){printf("Collection #%d:\nCan't be divided.\n\n",cas);continue;}v=sum/2;memset(dp,0,sizeof(dp));for(int i=0;i<6;i++)mp(i+1,i+1,n[i]);if(dp[v]==sum-v)printf("Collection #%d:\nCan be divided.\n\n",cas);else printf("Collection #%d:\nCan't be divided.\n\n",cas);}return 0; }
转载于:https://www.cnblogs.com/atmacmer/p/5366389.html
hdu和poj的基础dp30道相关推荐
- 扫描线三巨头 hdu1928hdu 1255 hdu 1542 [POJ 1151]
学习链接:http://blog.csdn.net/lwt36/article/details/48908031 学习扫描线主要学习的是一种扫描的思想,后期可以求解很多问题. 扫描线求矩形周长并 hd ...
- HDU 3966 POJ 3237 HYSBZ 2243 HRBUST 2064 树链剖分
树链剖分是一个很固定的套路 一般用来解决树上两点之间的路径更改与查询 思想是将一棵树分成不想交的几条链 并且由于dfs的顺序性 给每条链上的点或边标的号必定是连着的 那么每两个点之间的路径都可以拆成几 ...
- hdu与poj题目分类
POJ 初期: 一.基本算法: (1)枚举. (poj1753,poj2965) (2)贪心(poj1328,poj2109,poj2586) (3)递归和分治法. (4)递推. (5)构造法.(po ...
- c语言编辑87152,POJ 3287 (基础BFS) Catch That Cow
这是做的第一道BFS,很基础很简单的题目 广度优先搜索算法如下:(用QUEUE) (1) 把初始节点S0放入Open表中: (2) 如果Open表为空,则问题无解,失败 退出: (3) 把Open表的 ...
- hdu 5023 poj 2777(线段染色)2014 ACM/ICPC Asia Regional 广州 Online
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5023 http://poj.org/problem?id=2777 题意:给出一个长度为N的线段,分 ...
- BTA 常问的 Java基础40道常见面试题及详细答案,java初级面试笔试题
我总结出了很多互联网公司的面试题及答案,并整理成了文档,以及各种学习的进阶学习资料,免费分享给大家. 扫描二维码或搜索下图红色VX号,加VX好友,拉你进[程序员面试学习交流群]免费领取.也欢迎各位一起 ...
- java基础50道编程题
50道JAVA基础编程练习题 [程序1] 题目:古典问题:有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子对数为多少? 程序分析 ...
- hdu 1520 Anniversary party(第一道树形dp)
传送门: http://acm.hdu.edu.cn/showproblem.php?pid=1520 Anniversary party Time Limit: 2000/1000 MS (Java ...
- BTA 常问的 Java基础40道常见面试题及详细答案
最近看到网上流传着,各种面试经验及面试题,往往都是一大堆技术题目贴上去,而没有答案. 为此我业余时间整理了,Java基础常见的40道常见面试题,及详细答案,望各路大牛,发现不对的地方,不吝赐教,留言即 ...
- POJ 1573 POJ 2632(两道有趣的Robot)实例
/* ** POJ 2632 Crashing Robots ** Created by Rayn @@ 2014/04/16 ** 坑爹的模拟题,脑壳不清晰的就要被坑惨了 */ #include & ...
最新文章
- NDK JNI Android Studio开发与调试DEMO(三)(生成 .so 文件)
- 数据库索引-基本知识
- 青龙羊毛——垦荒新生活
- Java——多线程(铁路售票系统案例)
- curl 请求日志_kong api网关日志 将请求和响应数据附加到磁盘上的日志文件中
- 37--计算一个字符串中每个字符出现次数
- 深度学习实验1:pytorch实践与前馈神经网络
- python 微服务架构实战_《分布式服务架构:原理、设计与实战》第一章分布式微服务架构设计原理...
- 使用分层网络模型的两个优点是什么_从零开始学网络|搞懂OSI参考模型和TCP/IP分层模型,看这篇文章就够了...
- 【数字逻辑与EDA技术】数字电子技术基础-期末考试重点总结
- Python实现人脸识别
- Spring Cloud 常用注解
- 小马哥------山寨苹果6s(A9900-912G61-B 尾插盖板A953标示刷机拆机准图与开机识别图 低配机
- 关于《ERP原理》的读书笔记和思考(二)_ERP原理初探
- phpcms v9给栏目添加自定义英文栏目名称字段图文教程
- 得分——UVa1585
- 关于机械键盘的一些基础知识
- 【论文笔记】基于 VR 的移动机器人真实环境三维建模系统
- 结构体在cuda核函数里面不能用吗_求职招聘 | 面试机器学习职位,这些知识点你都会了吗?...
- It is indirectly referenced from required .class files