15.3.14 DP练习2
来源:互联网 发布:乐视视频显示网络异常 编辑:程序博客网 时间:2024/06/04 00:45
拦截导弹
题目
某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统。但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度。某天,雷达捕捉到敌国的导弹来袭。由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹。
输入数据:
第一行为一个整数N,表示飞来的导弹个数,N<=100000
第二行为N个整数,依次表示导弹飞来的高度,高度数据为不大于30000的正整数。
输出数据:
第一行,输出计算这套系统最多能拦截多少导弹
第二行,输出要拦截所有导弹最少要配备多少套这种导弹拦截系统。
输入文件:missile.in
8
389 207 155 300 299 170 158 65
输出文件:missile.out
6 2
分析
求个最长不上升子序列长度,一个上升子序列长度。
由于数据范围奇葩,所以用单调栈乱搞到
代码
#include <cstdio>#include <string>#include <algorithm>#define R1(i,n) for(register int i=1;i<=n;++i)using namespace std;template <class T> inline void read(T&x){ bool f=false;char ch; for(ch=getchar();ch<=32;ch=getchar()); if (ch=='-')f=true,ch=getchar(); for(x=0;ch>32;ch=getchar()) x=x*10+ch-'0'; if(f)x=-x;}template <class T> inline void write(T x){ if(x<0)putchar('-'),x=-x; if(x<10)putchar(x + '0'); else write(x / 10),putchar(x%10+'0');}template <class T> inline void writeln(T x){ write(x);puts("");}void setIO(string t){string a=t+".in",b=t+".out";freopen(a.c_str(),"r",stdin);freopen(b.c_str(),"w",stdout);}int n,cnt;int s1[100010],s2[100010],temp;int main(){ setIO("missile"); read(n); int top1=0,top2=0; s1[0]=-1,s2[0]=0x3f3f3f3f; R1(i,n){ read(temp); if(temp>s1[top1])s1[++top1]=temp; else{ int _l=1,_r=top1; int mid; while(_l<=_r){ mid=(_l+_r)/2; if(temp>s1[mid])_l=mid+1; else _r=mid-1; } s1[_l]=temp; } if(temp<=s2[top2])s2[++top2]=temp; else{ int _l=1,_r =top2; int mid; while(_l<=_r){ mid=(_l+_r)/2; if (temp<=s2[mid])_l=mid+1; else _r=mid-1; } s2[_l]=temp; } }writeln(top2),writeln(top1);return 0;}
整数划分
题目
如何把一个正整数N(N长度<20)划分为M(M>1)个部分,使这N个部分的乘积最大。N、M从键盘输入,输出最大值及一种划分方式。
输入数据:
第一行一个正整数T(T<=10000),表示有T组数据。
接下来T行每行两个正整数N,M。
输出数据:
对于每组数据
第一行输出最大值。
第二行输出划分方案,将N按顺序分成M个数输出,两个数之间用空格格开。
样例
输入文件:separate.in
1
199 2
输出文件:separate.out
171
19 9
WA的代码= =
#include <cstdio>#include <string>#include <cstring>#include <algorithm>#define R1(i,n) for(register int i=1;i<=n;++i)#define R0(i,n) for(register int i=0;i<n;++i)#define r(i,s,t) for(register int i=s;i<=t;++i)#define cl(a,m) memset(a,m,sizeof(a))using namespace std;template <class T> inline void read(T&x){ bool f=false;char ch; for(ch=getchar();ch<=32;ch=getchar()); if (ch=='-')f=true,ch=getchar(); for(x=0;ch>32;ch=getchar()) x=x*10+ch-'0'; if(f)x=-x;}template <class T> inline void write(T x){ if(x<0)putchar('-'),x=-x; if(x<10)putchar(x + '0'); else write(x / 10),putchar(x%10+'0');}template <class T> inline void writeln(T x){ write(x);puts("");}void setIO(string t){string a=t+".in",b=t+".out";freopen(a.c_str(),"r",stdin);freopen(b.c_str(),"w",stdout);}long long g[500][500],f[500][500],v[500][500];char s[23];void print(int p,int d){ if(d==0)return; print(g[p][d],d-1); r(i,g[p][d],p-1)write(s[i]-'0'); putchar(' ');}int m,t;int main(){ setIO("separate"); read(t); while(t--){ scanf("%s",s); read(m); int l=strlen(s); R1(i,l){ int sum=0; r(j,i,l){ //if(s[j-1]>0) sum=sum*10+s[j-1]-'0', v[i][j]=sum; } } cl(f,-1); f[0][0]=1; R1(i,l) R1(j,min(i,m)) R1(k,i){ if(f[k-1][j-1]*v[k][i]>f[i][j]){ f[i][j]=f[k-1][j-1]*v[k][i]; g[i][j]=k-1; } } writeln(f[l][m]); print(l,m); puts(""); } return 0;}
快餐问题
题目
Peter最近在R市开了一家快餐店,为了招揽顾客,该快餐店准备推出一种套餐,该套餐由A个汉堡,B个薯条和C个饮料组成。价格便宜。为了提高产量,Peter从著名的麦当劳公司引进了N条生产线。所有的生产线都可以生产汉堡,薯条和饮料,由于每条生产线每天所能提供的生产时间是有限的、不同的,而汉堡,薯条和饮料的单位生产时间又不同。这使得Peter很为难,不知道如何安排生产才能使一天中生产的套餐产量最大。请你编一程序,计算一天中套餐的最大生产量。为简单起见,假设汉堡、薯条和饮料的日产量不超过100个。
输入数据:
第一行为三个不超过100的正整数A、B、C中间以一个空格分开。
第二行为3个不超过100的正整数p1,p2,p3分别为汉堡,薯条和饮料的单位生产耗时。中间以一个空格分开。
第三行为为一个整数N (0<=0<=10),表示有N条流水线
第四行为N个不超过10000的正整数,其中Ti表示第i条生产流水线每天提供的生产时间,中间以一个空格分开。
输出数据:
仅一行,即每天套餐的最大产量。
输入文件:meal.in
2 2 2
1 2 2
2
6 6
输出文件:meal.out
1
代码
#include <cstdio>#include <string>#include <algorithm>#define R1(i,n) for(register int i=1;i<=n;++i)using namespace std;template <class T> inline void read(T&x){ bool f=false;char ch; for(ch=getchar();ch<=32;ch=getchar()); if (ch=='-')f=true,ch=getchar(); for(x=0;ch>32;ch=getchar()) x=x*10+ch-'0'; if(f)x=-x;}template <class T> inline void write(T x){ if(x<0)putchar('-'),x=-x; if(x<10)putchar(x + '0'); else write(x / 10),putchar(x%10+'0');}template <class T> inline void writeln(T x){ write(x);puts("");}void setIO(string t){string a=t+".in",b=t+".out";freopen(a.c_str(),"r",stdin);freopen(b.c_str(),"w",stdout);}int A,B,C,p1,p2,p3,n,t[20],ans;int f[20][101][101][101];int main(){ setIO("meal"); //f[i][a][b][c] : 前i条流水线, 生产a个汉堡,b个薯条,c个饮料的最大套餐产量 read(A),read(B),read(C); read(p1),read(p2),read(p3); if(!p1 && !p2 && !p3){writeln(0);return 0;} read(n); R1(i,n)read(t[i]),t[i]+=t[i-1];// R1(i,n)R1(j,n)R1(k,n)f[0][i][j][k]=0; R1(i,n) for(register int a=A;a*p1<=t[i]&&a<=100;++a) for(register int b=B;a*p1+b*p2<=t[i]&&b<=100;++b) for(register int c=C;a*p1+b*p2+c*p3<=t[i]&&c<=100;++c){ ans=max(ans,f[i][a][b][c]=max(f[i][a-A][b-B][c-C]+1,max(f[i-1][a-A][b-B][c-C]+1,f[i][a][b][c]))); //if(f[i][a][b][c])printf("f[%d][%d][%d][%d] = %d\n",i,a,b,c,f[i][a][b][c]); }writeln(ans);}
物品装箱问题
题目
设有n种物品,记作A1、A2、…、An,对应于每个Ai(1<=i<=n)都有一个重量Awi和价值Avi(重量和价值都为正整数)。另外,对应于每个Ai,都有一件可代替它的“代用品”Bi,Bi的重量和价值分别为Bwi和Bvi。
本题的任务是:选择这n件物品或其代用品的一个子集装进背包,使总重量不超过给定重量TOT,同时使总价值VAL最高。装填的第I步,要么装入Ai,要么装入Bi,要么Ai和Bi都不装。
输入数据:
第一行:n TOT ,n<=100, TOT<=10000
第二行:AW1 A v1 B W1 Bv1
第三行:AW2 A v2 B W2 Bv2
……
第n+1行:AWn A vn B Wn Bvn
输入数据:
只有一个数为最大的价值
输入文件:box.in
4 20
8 20 12 31
2 3 9 20
13 31 11 12
8 9 13 36
输出文件:box.out
40
分析
01背包
三选一乱搞
代码
#include <cstdio>#include <string>#include <algorithm>#define mn 200#define mt 10020#define R1(i,n) for(register int i=1;i<=n;++i)using namespace std;template <class T> inline void read(T&x){ bool f=false;char ch; for(ch=getchar();ch<=32;ch=getchar()); if (ch=='-')f=true,ch=getchar(); for(x=0;ch>32;ch=getchar()) x=x*10+ch-'0'; if(f)x=-x;}template <class T> inline void write(T x){ if(x<0)putchar('-'),x=-x; if(x<10)putchar(x + '0'); else write(x / 10),putchar(x%10+'0');}template <class T> inline void writeln(T x){ write(x);puts("");}void setIO(string t){string a=t+".in",b=t+".out";freopen(a.c_str(),"r",stdin);freopen(b.c_str(),"w",stdout);}int n,tot;int f[mt],a_w[mn],a_v[mn],b_w[mn],b_v[mn];int main(){ setIO("box"); read(n),read(tot); R1(i,n)read(a_w[i]),read(a_v[i]),read(b_w[i]),read(b_v[i]); R1(i,n)for(register int j=tot;j>=min(a_w[i],b_w[i]);--j){ f[j]=(j>=a_w[i]? max(f[j],f[j-a_w[i]]+a_v[i]):f[j]); f[j]=(j>=b_w[i]? max(f[j],f[j-b_w[i]]+b_v[i]):f[j]); } writeln(f[tot]);}
又是颓废的一天= = 队长又要喷我了orz
- 15.3.14 DP练习2
- DP练习2:道路游戏
- DP练习
- dp练习
- hdu2196--Computer(树形DP练习2)
- dp专题练习
- 数位DP练习
- 【线性DP】基础练习
- 学校作业-Dp练习
- 15.2.27 DP练习
- DP练习☞ <美元>
- DP专题练习题解
- DP练习 - 机器分配
- 区间DP练习
- dp练习orz
- 状压dp练习
- 数位DP练习
- 10.26 dp练习
- iOS中多种方式实现打电话、发短信、写邮件
- 第1周-项目2-长方柱类
- IPSec,SSL VPN以及OpenVPN引发些许感慨
- p27第4题
- 约瑟夫环问题
- 15.3.14 DP练习2
- CocoaPods 的使用
- string.ToLowerCase()用法
- 输出1000—2000年之间的所有闰年
- Chrome去广告《广告终结者》
- 回文串数dp(uvaAgain Palindromes )
- Eclipse 使用
- 全局变量与局部变量
- .dll与.so文件的区别和构成