题目转自: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. 【完全背包】HDU 1284 钱币兑换问题

    Problem Description 在一个国家仅有1分,2分,3分硬币,将钱N兑换成硬币有很多种兑法.请你编程序计算出共有多少种兑法. Input 每行只有一个正整数N,N小于32768. Out ...

  2. 系统不识别某些Android设备:adb devices不显示问题解决

    1.获取厂商android设备ID 电脑连接android设备,然后执行命令: system_profiler SPUSBDataType 2.将厂商ID添加到 adb_usb.ini 文件中 Mac ...

  3. NASPhoto Station不只是储存的强大照片管理功能

    减少漫长的讨论时间,进而让你的艺术作品更符合客户需求.Photo Station 让你集中存储照片.随处分享及存取相簿并轻松收集朋友和客户反馈. 串流照片到大屏幕电视 DS photo 支援 Appl ...

  4. Apache php无法开启php_curl

    解决办法: 将php安装目录下的libeay32.dll,libssh2.dll,php5ts.dll,php_curl.dll,ssleay32.dll 复制到system32目录下 在httpd. ...

  5. PHP-FPM进程数的设定

    近日,服务器出现异常,网站不能正常访问.经排查是php的问题. 在重启php-fpm时,恢复正常.1分钟之后又出现故障.查看php日志文件 /usr/local/php/var/log 后提示 WAR ...

  6. [转]Delphi中QuotedStr介绍及使用

    转自:http://www.360doc.com/content/13/0524/09/7873422_287679198.shtml 使用S:string; qry2.SQL.add('select ...

  7. SAP HANA中创建层次分析视图(Hierarchy Analytic View)

    1. 创建层次Attribute View: ATTR_PRODUCT_HIERACHY ref:  http://www.cnblogs.com/omygod/archive/2013/04/30/ ...

  8. github上前100的ios项目

    1. AFNetworking    作者是 NSHipster 的博主, iOS 开发界的大神级人物, 毕业于卡内基·梅隆大学, 开源了许多牛逼的项目, 这个便是其中之一, AFNetworking ...

  9. VMware下安装CentOS6.5

    一.工具 1.VMware-workstation-full-12.5.0-4352439.exe 2.CentOS-6.5-x86_64-minimal.iso 二.安装VMware虚拟机 1.选择 ...

  10. JAVA读取本地配置文件实例

    import java.io.InputStream; import java.util.Properties; public class FileProperties extends Propert ...