15.3.14 DP练习2

拦截导弹

题目

某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统。但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度。某天,雷达捕捉到敌国的导弹来袭。由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹。



输入数据:

第一行为一个整数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


代码

#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

时间: 2024-10-10 09:39:16

15.3.14 DP练习2的相关文章

15.2.27 DP练习

关键子工程(project.c/cpp/pas) 题目 在大型工程的施工前,我们把整个工程划分为若干个子工程,并把这些子工程编号为1.2.--.N:这样划分之后,子工程之间就会有一些依赖关系,即一些子工程必须在某些子工程完成之后才能施工.由于子工程之间有相互依赖关系,因此有两个任务需要我们去完成:首先,我们需要计算整个工程最少的完成时间:同时,由于一些不可预测的客观因素会使某些子工程延期,因此我们必须知道哪些子工程的延期会影响整个工程的延期,我们把有这种特征的子工程称为关键子工程,因此第二个任务

6.15 4.1-4.4

4.1 df命令 [[email protected] ~]# df 文件系统          1K-块    已用     可用 已用% 挂载点 /dev/sda3      18658304 1006236 17652068    6% / devtmpfs         494184       0   494184    0% /dev tmpfs            504076       0   504076    0% /dev/shm tmpfs            5

IOS学习笔记 ---- 15/09/14

1.Sqlite3数据库的创建顺序: 先使用C语言函数 [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] 来获得数据库的Document目录,再通过 stringByAppendingPathComponent 方法来拼接出数据库文件目录; 创建一个sqlite3的指针对象,并且赋予NULL值; 使用C语言函数 sqlite3_open(数据库目录.UTF8St

Html5 reset表 2015年1月7日15:02:14

/* HTML5 Reset :: style.css ---------------------------------------------------------- We have learned much from/been inspired by/taken code where offered from: Eric Meyer :: http://meyerweb.com HTML5 Doctor :: http://html5doctor.com and the HTML5 Bo

【2019.8.14】2019QB学堂DP图论班第一次考试 Problem C

Problem C Problem Description Tarzan 非常烦数轴因为数轴上的题总是难度非常大.不过他非常喜欢线段,因为有关线 段的题总是不难,讽刺的是在一个数轴上有 n 个线段,Tarzan 希望自己喜欢的东西和讨厌的 东西不在一起,所以他要把这些线段分多次带走,每一次带走一组,最多能带走 k 次.其实 就是要把这些线段分成至多 k 组,每次带走一组,问题远没有那么简单,tarzan 还希望每次 选择的线段组都很有相似性,我们定义一组线段的相似性是组内线段交集的长度,我们现在

POJ - 3186 Treats for the Cows (区间DP)

题目链接:http://poj.org/problem?id=3186 题意:给定一组序列,取n次,每次可以取序列最前面的数或最后面的数,第n次出来就乘n,然后求和的最大值. 题解:用dp[i][j]表示i~j区间和的最大值,然后根据这个状态可以从删前和删后转移过来,推出状态转移方程: dp[i][j]=max(dp[i+1][j]+value[i]*k,dp[i][j-1]+value[j]*k) 1 #include <iostream> 2 #include <algorithm&

poj 1088 滑雪 DP(dfs的记忆化搜索)

题目地址:http://poj.org/problem?id=1088 题目大意:给你一个m*n的矩阵 如果其中一个点高于另一个点 那么就可以从高点向下滑 直到没有可以下滑的时候 就得到一条下滑路径 求最大的下滑路径 分析:因为只能从高峰滑到低峰,无后效性,所以每个点都可以找到自己的最长下滑距离(只与自己高度有关).记忆每个点的最长下滑距离,当有另一个点的下滑路径遇到这个点的时候,直接加上这个点的最长下滑距离. dp递推式是,dp[x][y] = max(dp[x][y],dp[x+1][y]+

简单的dp

1 有趣的数:(动态规划,状态转移) 2 #include<stdio.h> 3 int dp[6][1001]; 4 int main() 5 { 6 int n,i; 7 for(i=0; i<6; i++) 8 dp[i][0]=0; 9 while(~scanf("%d",&n)) 10 { 11 for(i=1; i<=n; i++) 12 { 13 dp[0][i]=1; 14 dp[1][i]=dp[0][i-1]+dp[1][i-1];

timus 1225 flags 基础DP 简单递推

1225. Flags Time limit: 1.0 secondMemory limit: 64 MB On the Day of the Flag of Russia a shop-owner decided to decorate the show-window of his shop with textile stripes of white, blue and red colors. He wants to satisfy the following conditions: Stri