题目转自: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;//一个银行都不抢 成功逃走的概率为1
for(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;
}

hdu和poj的基础dp30道的更多相关文章

  1. Coins HDU - 2844 POJ - 1742

    Coins HDU - 2844 POJ - 1742 多重背包可行性 当做一般多重背包,二进制优化 #include<cstdio> #include<cstring> in ...

  2. Eight hdu 1043 poj 1077

    Description The 15-puzzle has been around for over 100 years; even if you don't know it by that name ...

  3. HDU 3695 / POJ 3987 Computer Virus on Planet Pandora(AC自动机)(2010 Asia Fuzhou Regional Contest)

    Description Aliens on planet Pandora also write computer programs like us. Their programs only consi ...

  4. hdu 2844 poj 1742 Coins

    hdu 2844 poj 1742 Coins 题目相同,但是时限不同,原本上面的多重背包我初始化为0,f[0] = 1;用位或进行优化,f[i]=1表示可以兑成i,0表示不能. 在poj上运行时间正 ...

  5. HDU 3265/POJ 3832 Posters(扫描线+线段树)(2009 Asia Ningbo Regional)

    Description Ted has a new house with a huge window. In this big summer, Ted decides to decorate the ...

  6. HDU 2494/POJ 3930 Elevator(模拟)(2008 Asia Regional Beijing)

    Description Too worrying about the house price bubble, poor Mike sold his house and rent an apartmen ...

  7. 扫描线三巨头 hdu1928&&hdu 1255 && hdu 1542 [POJ 1151]

    学习链接:http://blog.csdn.net/lwt36/article/details/48908031 学习扫描线主要学习的是一种扫描的思想,后期可以求解很多问题. 扫描线求矩形周长并 hd ...

  8. hdu 1540/POJ 2892 Tunnel Warfare 【线段树区间合并】

    Tunnel Warfare                                                             Time Limit: 4000/2000 MS ...

  9. HDU 3966 & POJ 3237 & HYSBZ 2243 树链剖分

    树链剖分是一个很固定的套路 一般用来解决树上两点之间的路径更改与查询 思想是将一棵树分成不想交的几条链 并且由于dfs的顺序性 给每条链上的点或边标的号必定是连着的 那么每两个点之间的路径都可以拆成几 ...

随机推荐

  1. 一步步优化JVM六:优化吞吐量

    如果你已经进行完了前面的步骤了,那么你应该知道这是最后一步了.在这一步里面,你需要测试应用的吞吐量和为了更高的吞吐量而优化JVM.    这一步的输入就是应用的吞吐量性能要求.应用的吞吐量是在应用层面 ...

  2. android studio依赖库工程Activity显示问题及库工程设置

    android studio引用库工程其实不难,直接添加依赖module即可,但是我在操作过程中出现一些奇怪的问题,苦扰我一整天,为了祭奠这苦命的一天特别mark一下. 首先描述一下我的错误现象: s ...

  3. BZOJ 1303 【CQOI2009】中位数图

    baidu了一下bzoj水题列表...找到这道题.   题目大意:给定一个数t,在给定的一段包含1-n的序列中找出多少个长度为奇数子序列的中位数为t. 第一眼没看数据范围,于是开心的打了一个O(n^3 ...

  4. Elasticsearch 5.0 _all field的简单认识

    前言:本文的目的是为后续磁盘空间利用优化做铺垫,主要知识点来源于官网 一._all 是什么 在Elasticsearch中,_all field维护这一个很大的字符串数组(text类型).这个字符串是 ...

  5. StringBuffer使用append提示String concatenation as argument to 'StringBuffer.append()' call

    昨天发现一个IDE提示: String concatenation as argument to 'StringBuffer.append()' call less... (Ctrl+F1) Repo ...

  6. USACO 3.3 Shopping Offers

    Shopping OffersIOI'95 In a certain shop, each kind of product has an integer price. For example, the ...

  7. js得到当前页面的url信息方法

    js得到当前页面的url信息方法:http://www.cnblogs.com/zuosong160522/p/5755615.html js获取url传递参数,js获取url?后面的参数:http: ...

  8. js作用域详解

    // 作用域:(1)域:空间.范围.区域……     (2) 作用:读.写 script 全局变量.全局函数 自上而下 函数 由里到外 浏览器: “JS解析器” 1)“找一些东西” :var func ...

  9. Openjudge-NOI题库-简单算术表达式求值

    题目描述 Description 两位正整数的简单算术运算(只考虑整数运算),算术运算为: +,加法运算:-,减法运算:*,乘法运算:/,整除运算:%,取余运算. 算术表达式的格式为(运算符前后可能有 ...

  10. CharSequence 接口

    java中有些方法需要用到CharSequence 类型的参数,笔者百度了一下,总结出一下几点: 1.CharSequence 是一个接口,可以直接用“=”赋值一段字符串,但是不能用new新建一个对象 ...