1.导弹拦截  (+贪心)

  两问:一个导弹拦截系统最多能拦多少导弹 要拦截所有导弹至少需要多少拦截系统

  第一问感觉是一个比较巧妙的方法:

    维护一个单调递减的序列 length[] 记录的是拦截导弹的高度

    当下一个导弹小于 length[] 最后一个数(最小的数)则直接把它加在序列后即可

    若大于 则找到序列中比它大的最小的数(二分)然后替换 可以保证最优

  第二问 就是贪心啊

    当现有的导弹系统的拦截高度都小于当前导弹的高度 则开一个新的系统

    否则找到拦截高度比导弹高度高的最小的系统来拦截

    这里记录系统拦截高度的数组一定是单调递增的无需排序

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int x;
bool f;
int height[],length[],minh[];
int main()
{
int y=;
while(scanf("%d",&height[y])==) y++;y--;
length[]=height[];
int top=;
for(int i=;i<=y;i++)
{
if(height[i]<=length[top]) length[++top]=height[i];
else
{
int left=,right=top,ans;
while(left<=right)
{
int mid=(left+right)/;
if(length[mid]<height[i])
{
ans=mid;
right=mid-;
}
else left=mid+;
}
length[ans]=height[i];
}
}
cout<<top<<endl;
int maxa=;
for(int i=;i<=y;i++)
if(maxa<length[i]) maxa=length[i];
int num=;minh[]=height[];
for(int i=;i<=y;i++)
{
f=;
for(int j=;j<=num;j++)
if(height[i]<=minh[j]) {minh[j]=height[i];f=;break;}
if(f==) minh[++num]=height[i];
}
cout<<num;
return ;
}

2.石子合并 (+断环为链法)

  区间dp一般套路:枚举起点 枚举区间长度(或终点) 枚举断点 转移

  注意枚举的顺序要保证由已知推未知

  很多时候遇到环都可能要断环为链(图论也是这样)

 #include<iostream>
using namespace std;
int a[];
int s[];
int ans1[][];
int ans2[][];
int main()
{
int n;
cin>>n;
for(int i=;i<=n;i++)
{
cin>>a[i];
s[i]=s[i-]+a[i];
a[i+n]=a[i];
}
for(int i=n+;i<=n*;i++)
s[i]=s[i-]+a[i];
for(int i=;i<=*n;i++)
for(int j=;j<=*n;j++)
if(j!=i) ans2[i][j]=;
for(int h=;h<=n;h++)
{
for(int i=h+n-;i>=h;i--)
{
for(int j=i;j<=h+n-;j++)
{
for(int k=i+;k<=j;k++)
{
ans1[i][j]=max(ans1[i][j],ans1[i][k-]+ans1[k][j]+s[j]-s[i-]);
ans2[i][j]=min(ans2[i][j],ans2[i][k-]+ans2[k][j]+s[j]-s[i-]);
}
}
}
}
int maxn,minn=;
for(int i=;i<=n;i++)
{
maxn=max(maxn,ans1[i][i+n-]);
minn=min(minn,ans2[i][i+n-]);
}
cout<<minn<<endl<<maxn<<endl;
return ;
}

.相似基因

  现在看起来好像很显然的样子

  f[i][j] 表示第一个字符串匹配到第i位 第二个字符串匹配到第j位最大的相似度

  三种情况转移 分别是在第一个,第二个字符串加空碱基 不加空碱基

  注意初始化

 #include<iostream>
#include<cstdio>
using namespace std;
int len1,len2,sum;
char s1[],s2[];
int a1[],a2[];
char ch;
int f[][];
int s[][]={{,,,,,},
{,,-,-,-,-},
{,-,,-,-,-},
{,-,-,,-,-},
{,-,-,-,,-},
{,-,-,-,-,}};
int change(char x)
{
if(x=='A') return ;
else if(x=='C') return ;
else if(x=='G') return ;
else if(x=='T') return ;
}
int main()
{
scanf("%d",&len1);ch=getchar();
for(int i=;i<=len1;i++) scanf("%c",&s1[i]);
scanf("%d",&len2);ch=getchar();
for(int i=;i<=len2;i++) scanf("%c",&s2[i]);
for(int i=;i<=len1;i++) a1[i]=change(s1[i]);
for(int i=;i<=len2;i++) a2[i]=change(s2[i]);
for(int i=;i<=len1;i++)
for(int j=;j<=len2;j++) f[i][j]=-;
for(int i=;i<=len1;i++) f[i][]=f[i-][]+s[a1[i]][];
for(int i=;i<=len2;i++) f[][i]=f[][i-]+s[a2[i]][];
for(int i=;i<=len1;i++)
{
for(int j=;j<=len2;j++)
{
f[i][j]=max(f[i][j],f[i-][j]+s[a1[i]][]);
f[i][j]=max(f[i][j],f[i][j-]+s[a2[j]][]);
f[i][j]=max(f[i][j],f[i-][j-]+s[a1[i]][a2[j]]);
}
}
printf("%d",f[len1][len2]);
return ;
}

4.传纸条(优化维度)

  四维dp 优化成三维

 #include<iostream>
#include<cstdio>
using namespace std;
int read()
{
int ans=;char c;
c=getchar();
while(c<''||c>'') c=getchar();
while(c>=''&&c<='') {ans=ans*+c-'';c=getchar();}
return ans;
}
int f[][][];
int a[][];
int main()
{
int m=read(),n=read();
for(int i=;i<=m;i++)
for(int j=;j<=n;j++)
a[i][j]=read();
for(int k=;k<=n+m;k++)
{
for(int i=;i<=n;i++)
{
for(int j=;j<=n;j++)
{
if(k-i+<||k-j+<) continue;
f[k][i][j]=max(max(max(f[k-][i][j],f[k-][i-][j]),f[k-][i][j-]),f[k-][i-][j-]);
f[k][i][j]+=a[k-i][i]+a[k-j][j];
if(i==j) f[k][i][j]-=a[k-i][i];
}
}
}
cout<<f[m+n][n][n];
return ;
}

5.花店橱窗布置

  这一题要输出最优方案 所以f[i][j]表示的是前i束花放在前j个瓶子里 且第i束花放在第j个瓶子里的最大美学值

 #include<iostream>
using namespace std;
int a[][]; //a[i][j] 第i束花放在第j个花瓶中的美学值
int b[][]; //b[i][j] 前i束花放在前j个花瓶中的最大美学值
int c[][],d[];
int main()
{
int f,v;
cin>>f>>v;
for(int i=;i<=f;i++)
for(int j=;j<=v;j++)
cin>>a[i][j];
//for(int i=1;i<=v-f+1;i++) b[1][i]=a[1][i];
for(int i=;i<=f;i++)
for(int j=;j<=v;j++)
b[i][j]=-;
/*如果b数组中初始值都为0
那么当第一束花放在前几个花瓶中美学值为负数时就会出错;
或:直接初始化第一束花放在前几个花瓶中的美学值(前面被注释掉的)
但注意此时后面一个循环的i从2开始*/ for(int i=;i<=f;i++)
for(int j=i;j<=v-f+i;j++) //j<=v-f+i!!!
for(int k=i-;k<=j-;k++)
{
if(b[i][j]<b[i-][k]+a[i][j])
{
b[i][j]=b[i-][k]+a[i][j];
c[i][j]=k;
}
}
int maxn=-,k;
for(int i=f;i<=v;i++)
{
if(b[f][i]>maxn)
{
maxn=b[f][i];
k=i;
}
}
cout<<maxn<<endl;
for(int i=;i<=f;i++)
{
d[i]=k;
k=c[f-i+][k];
}
for(int j=f;j>=;j--) cout<<d[j]<<" ";
return ;
}

6.编辑距离

  和3类似

 #include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
char a[],b[];
int f[][];
int main()
{
int m,n,i,j;
scanf("%s%s",a,b);
m=strlen(a);n=strlen(b);
for(int i=m+;i>=;i--) a[i]=a[i-];
for(int j=n+;j>=;j--) b[j]=b[j-];
for(i=;i<=m;i++) f[i][]=i;
for(j=;j<=n;j++) f[][j]=j;
for(i=;i<=m;i++)
{
for(j=;j<=n;j++)
{
if(a[i]==b[j]) f[i][j]=f[i-][j-];
else
{
f[i][j]=min(min(f[i-][j-],f[i-][j]),f[i][j-])+;
}
}
}
cout<<f[m][n];
return ;
}

7.乘积最大

  f[i][j] 表示到第i位数已经加了j个乘号的最大乘积

  加高精有点麻烦啊

 #include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#define rg register
#define M 110
using namespace std;
int read()
{
int x=,y=;char c;
c=getchar();
while(c<''||c>'') {if(c=='-') y=-;c=getchar();}
while(c>=''&&c<='') {x=(x<<)+(x<<)+c-'';c=getchar();}
return x*y;
}
string ss;
int n1,k1;
int a[M];
struct node
{
int s[M];
int len;
}f[][M];
node calc(node x,int l,int r)
{
node x1,y1;y1.len=r-l+;
int len1=x.len,len2=y1.len,len=len1+len2-;
memset(x1.s,,sizeof(x1.s));
memset(y1.s,,sizeof(y1.s));
for(rg int i=r;i>=l;i--) y1.s[r-i+]=a[i];
for(rg int i=;i<=len1;i++)
for(rg int j=;j<=len2;j++)
x1.s[i+j-]+=x.s[i]*y1.s[j];
for(rg int i=;i<=len;i++)
{
x1.s[i+]+=x1.s[i]/;
x1.s[i]%=;
}
if(x1.s[len+]) len++;
x1.len=len;
return x1;
}
node cmp(node x,node y)
{
int len1=x.len,len2=y.len;
if(len1<len2) return y;
if(len1>len2) return x;
for(rg int i=len1;i>=;i--)
{
if(x.s[i]>y.s[i]) return x;
if(x.s[i]<y.s[i]) return y;
}
return y;
}
int main()
{
n1=read();k1=read();
cin>>ss;
for(int i=;i<=n1;i++) a[i]=ss[i-]-'';
for(int i=;i<=n1;i++)
for(int j=i;j>=;j--)
f[][i].s[++f[][i].len]=a[j];
for(int i=;i<=n1;i++) //前i个数
{
int maxn=min(i-,k1);
for(int k=;k<=maxn;k++)//k个乘号
for(int j=k;j<i;j++)//第k个乘号放哪
f[k][i]=cmp(f[k][i],calc(f[k-][j],j+,i));
}
for(int i=f[k1][n1].len;i>=;i--)
printf("%d",f[k1][n1].s[i]);
return ;
}

回顾一些较简单的dp题的更多相关文章

  1. 从一道简单的dp题中学到的...

    今天想学点动态规划的知识,于是就看了杭电的课件,数塔问题啊,LCS啊都是比较经典的动规了,然后随便看了看就开始做课后练习题... HDOJ 1421 搬寝室 http://acm.hdu.edu.cn ...

  2. 一道简单的dp题 --- Greenhouse Effect CodeForces - 269B

    题目链接: https://vjudge.net/problem/36696/origin 题目大意: 要求从1到m升序排列,点可以随意移动,问最少需要移动多少次, 思路: 动态规划 可以推出转移方程 ...

  3. [DP题]吃糖果

    1944:吃糖果 总时间限制:1000ms内存限制:65536kB 描述 名名的妈妈从外地出差回来,带了一盒好吃又精美的巧克力给名名(盒内共有 N 块巧克力,20 > N >0).妈妈告诉 ...

  4. [DP题]采药

    1775:采药 总时间限制:1000ms内存限制:65536kB 描述 辰辰是个很有潜能.天资聪颖的孩子,他的梦想是称为世界上最伟大的医师.为此,他想拜附近最有威望的医师为师.医师为了判断他的资质,给 ...

  5. [DP题]最长上升子序列

    最长上升子序列 总时间限制:2000ms 内存限制:65536kB 描述 一个数的序列bi,当b1 < b2 < ... < bS的时候,我们称这个序列是上升的.对于给定的一个序列( ...

  6. poj 2342 Anniversary party 简单树形dp

    Anniversary party Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 3862   Accepted: 2171 ...

  7. HDU 3853LOOPS(简单概率DP)

    HDU 3853    LOOPS 题目大意是说人现在在1,1,需要走到N,N,每次有p1的可能在元位置不变,p2的可能走到右边一格,有p3的可能走到下面一格,问从起点走到终点的期望值 这是弱菜做的第 ...

  8. 古韵之乞巧 题解 dp题

    [noip模拟赛1]古韵之乞巧   描述 闺女求天女,更阑意未阑. 玉庭开粉席,罗袖捧金盘. 向月穿针易,临风整线难. 不知谁得巧,明旦试相看. ——祖咏<七夕> 女子乞巧,是七夕的重头戏 ...

  9. [10.27_P2] 统计损失 (简单树形DP)

    树形DP 简单题 Description 给定一棵树,每个节点有一个值.对于一条路径,它的值为路径上所有点的值的乘积.求出树上所有路径的值的和. 注意:单个点也算一条路径. Input 第 1 行一个 ...

随机推荐

  1. 【转载】HttpWebRequest的GetResponse或GetRequestStream偶尔超时 + 总结各种超时死掉的可能和相应的解决办法

    [问题] 用C#模拟网页登陆,其中去请求几个页面,会发起对应的http的请求request,其中keepAlive设置为true,提交请求后,然后会有对应的response: resp = (Http ...

  2. ACdream1092

    题意是给出某个地鼠的出现位置以及出现时间,人有一个移动速度,求此人最多可以打多少个地鼠? 我们根据时间把所有的地鼠排序,如果两个地鼠之间的距离不超过时间只差与速度的乘积,那说明打完上一只地鼠还可以打到 ...

  3. mysql时间函数和时间操作

    补 原文链接:http://blog.csdn.net/yuxiayiji/article/details/7480785 select timediff('23:40:00', ' 18:30:00 ...

  4. python selenium2 定位一组元素find_elements实例

    打开hao123首页,需要定位以上区域中的所有链接,他们有相同的父元素<ul class="js_bd site-bd site-hd0">,所有链接处在li>a ...

  5. 【刷题】BZOJ 2588 Spoj 10628. Count on a tree

    Description 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K小的点权.其中lastans是上一个询问的答案,初始 ...

  6. js关闭当前页面窗口的问题

    有两种情况,如果当前页面窗口是由js代码打开的,那么可以直接用js关闭该窗口 如: window.close(); 如果该页面是由用户输入地址直接进去的,直接close是会无效的,此时需要这样做: w ...

  7. centos下安装ngnix+php+mysql服务

    一.nginx 安装 1.查看yum下nginx版本信息 [root@localhost ~]# yum list | grep nginx 2.手动添加nginx的yum仓库 [root@local ...

  8. 卡特兰数Catalan——定义、公式、模型总结

    推荐:卡特兰数总结 定义: f(i)表示,从(0,0)出发,到(i,i),每次只能向上或者向右走,并且不越过红线的方案数. 这个图片的点上的数字,其实告诉我们f[i],就可以根据这个n方dp得到. 其 ...

  9. git 利用hook 实现服务器自动更新代码

    如何利用git的hook实现提交代码后自动更新? 因为个人开发经常需要提交代码,每次都需要连接服务器去pull代码,重启服务器就显得十分繁琐,因此github提供了一个时间钩子,用户push代码后可以 ...

  10. 2018-2019 ACM-ICPC ECfinal I. Misunderstood … Missing

    题目链接 首先有两个个属性值:\(A,D\),其中\(A\)表示目前攻击力,\(D\)表示每回合攻击的增量. 现在一共有\(n\)个回合,每一回合\(i\),可以有以下三种操作: 1.进行攻击,造成\ ...