回顾一些较简单的dp题
两问:一个导弹拦截系统最多能拦多少导弹 要拦截所有导弹至少需要多少拦截系统
第一问感觉是一个比较巧妙的方法:
维护一个单调递减的序列 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 ;
}
区间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 ;
}
四维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 ;
}
这一题要输出最优方案 所以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 ;
}
和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 ;
}
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题的更多相关文章
- 从一道简单的dp题中学到的...
今天想学点动态规划的知识,于是就看了杭电的课件,数塔问题啊,LCS啊都是比较经典的动规了,然后随便看了看就开始做课后练习题... HDOJ 1421 搬寝室 http://acm.hdu.edu.cn ...
- 一道简单的dp题 --- Greenhouse Effect CodeForces - 269B
题目链接: https://vjudge.net/problem/36696/origin 题目大意: 要求从1到m升序排列,点可以随意移动,问最少需要移动多少次, 思路: 动态规划 可以推出转移方程 ...
- [DP题]吃糖果
1944:吃糖果 总时间限制:1000ms内存限制:65536kB 描述 名名的妈妈从外地出差回来,带了一盒好吃又精美的巧克力给名名(盒内共有 N 块巧克力,20 > N >0).妈妈告诉 ...
- [DP题]采药
1775:采药 总时间限制:1000ms内存限制:65536kB 描述 辰辰是个很有潜能.天资聪颖的孩子,他的梦想是称为世界上最伟大的医师.为此,他想拜附近最有威望的医师为师.医师为了判断他的资质,给 ...
- [DP题]最长上升子序列
最长上升子序列 总时间限制:2000ms 内存限制:65536kB 描述 一个数的序列bi,当b1 < b2 < ... < bS的时候,我们称这个序列是上升的.对于给定的一个序列( ...
- poj 2342 Anniversary party 简单树形dp
Anniversary party Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 3862 Accepted: 2171 ...
- HDU 3853LOOPS(简单概率DP)
HDU 3853 LOOPS 题目大意是说人现在在1,1,需要走到N,N,每次有p1的可能在元位置不变,p2的可能走到右边一格,有p3的可能走到下面一格,问从起点走到终点的期望值 这是弱菜做的第 ...
- 古韵之乞巧 题解 dp题
[noip模拟赛1]古韵之乞巧 描述 闺女求天女,更阑意未阑. 玉庭开粉席,罗袖捧金盘. 向月穿针易,临风整线难. 不知谁得巧,明旦试相看. ——祖咏<七夕> 女子乞巧,是七夕的重头戏 ...
- [10.27_P2] 统计损失 (简单树形DP)
树形DP 简单题 Description 给定一棵树,每个节点有一个值.对于一条路径,它的值为路径上所有点的值的乘积.求出树上所有路径的值的和. 注意:单个点也算一条路径. Input 第 1 行一个 ...
随机推荐
- Mysql 定位执行效率低的sql 语句
一.通过MySQL慢查询日志定位执行效率低的SQL语句. MySQL通过慢查询日志定位那些执行效率较低的SQL 语句,用--log-slow-queries[=file_name]选项启动时,mysq ...
- [转帖]SQLSERVER的兼容级别
SQL Server数据库的兼容级别 http://www.cnblogs.com/sosoft/archive/2017/07/08/sqljrjb.html 改天尝试一下 在SQLSERVER20 ...
- poj 2299 Ultra-QuickSort(树状数组求逆序数)
链接:http://poj.org/problem?id=2299 题意:给出n个数,求将这n个数从小到大排序,求使用快排的需要交换的次数. 分析:由快排的性质很容易发现,只需要求每个数的逆序数累加起 ...
- 用java和junit编写app自动化测试用例
package myTest; import static org.junit.Assert.*; import io.appium.java_client.android.AndroidDriver ...
- Codeforces 449B_Jzzhu and Cities
给一个无向图,外加一些特殊的连接原点的无向边.在不改变原点与所有点的最短路的情况下,最多可以删除多少条特殊边? 首先我们把所有的边夹杂在一起.spfa跑出与所有点的最短路. 接下来我们通过一次bfs来 ...
- MT【141】逆用特征根法
(清华大学THUSSAT) 已知 \(a=\left( \dfrac{-1+\sqrt{5}}{2} \right)^{-10}+\left( \dfrac{-1-\sqrt{5}}{2} \righ ...
- hdu 3307 简单的指数循环节
#include<stdio.h>#include<string.h>#include<algorithm>#define LL __int64using name ...
- [洛谷P4091][HEOI2016/TJOI2016]求和
题目大意:给你$n(n\leqslant10^5)$,求:$$\sum\limits_{i=0}^n\sum\limits_{j=0}^i\begin{Bmatrix}i\\j\end{Bmatrix ...
- Spring点滴二:Spring Bean
Spring Bean: 被称作bean的对象是构成应用程序的支柱,是由Spring Ioc容器管理.bean是一个被实例化,配置.组装并由Spring Ioc容器管理对象. 官网API:A Spri ...
- P4051 [JSOI2007]字符加密 解题报告
P4051 [JSOI2007]字符加密 题目描述 喜欢钻研问题的JS 同学,最近又迷上了对加密方法的思考.一天,他突然想出了一种他认为是终极的加密办法:把需要加密的信息排成一圈,显然,它们有很多种不 ...