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. 解决win10激活错误代码0xc004c003

    打开命令窗口(管理员). win10电脑图解-2 输入slmgr.vbs /upk,回车 激活错误电脑图解-3 输入:slmgr /ipk W269N-WFGWX-YVC9B-4J6C9-T83GX, ...

  2. [转帖]go的调度机制.

    调度器 主要基于三个基本对象上,G,M,P(定义在源码的src/runtime/runtime.h文件中) G代表一个goroutine对象,每次go调用的时候,都会创建一个G对象 M代表一个线程,每 ...

  3. sql学习. case + group by 都干了啥子事情

    select case pref_name when 'fudao' then 'siguo' when 'xiangchuan' then 'siguo' when 'aiyuan' then 's ...

  4. DPDK环境搭建

    一.环境要求  1.内核版本 >= 2.6.34:  2.glibc版本 >= 2.7 (ldd --version 查看glibc版本):  3.gcc版本 >= 4.9,一些gc ...

  5. 02.基于IDEA+Spring+Maven搭建测试项目--详细过程

    一.背景介绍 1.1公司相关技术 Git:是一款免费的开源的分布式版本控制系统,用于敏捷高效地处理任何或小或大的项目,方便多人集成开发 Maven:是基于项目对象模型(POM),可以通过一小段描述信息 ...

  6. STL 基本概念

    STL 基本概念 STL(Standard Template Library,标准模板库)是惠普实验室开发的一系列软件的统称.现在是一个C++软件库,也是C++标准程序库的一部分,但在被引入C++之前 ...

  7. 【刷题】BZOJ 3144 [Hnoi2013]切糕

    Description Input 第一行是三个正整数P,Q,R,表示切糕的长P. 宽Q.高R.第二行有一个非负整数D,表示光滑性要求.接下来是R个P行Q列的矩阵,第z个 矩阵的第x行第y列是v(x, ...

  8. [USACO12NOV]同时平衡线Concurrently Balanced Strings DP map 思维

    题面 [USACO12NOV]同时平衡线Concurrently Balanced Strings 题解 考虑DP. \(f[i]\)表示以\(i\)为左端点的合法区间个数.令\(pos[i]\)表示 ...

  9. 洛谷 P4363 [九省联考2018]一双木棋chess 解题报告

    P4363 [九省联考2018]一双木棋chess 题目描述 菲菲和牛牛在一块\(n\)行\(m\)列的棋盘上下棋,菲菲执黑棋先手,牛牛执白棋后手. 棋局开始时,棋盘上没有任何棋子,两人轮流在格子上落 ...

  10. [USACO18OPEN]Out of Sorts P 冒泡排序理解之二

    题目描述 Bessie把快速排序和冒泡排序混在了一起 给一个伪快排的代码: 冒泡: bubble_sort_pass (A) { to length(A)- ], swap A[i] and A[i+ ...