The Triangle  http://poj.org/problem?id=1163

暴力dfs的话,每个节点有两条路可以走,那么n个节点复杂度就是2^n  n=100  超时   dp来做 就优化成 n^2

记忆化搜索,就能优化成n^2 因为一个点最多算一次,以后会直接返回dp i j 。 dp i j 表示这个位置能获得最大值。最后一行就是a i j  ,其他行都可以由下面两条路取最大值。

 #include<cstdio>
#include<cstring>
#include<algorithm>
#define mt(a,b) memset(a,b,sizeof(a))
using namespace std;
const int M=;
int n,a[M][M],dp[M][M];
int dfs(int i,int j){
if(~dp[i][j]) return dp[i][j];
if(i==n) dp[i][j]=a[i][j];
else dp[i][j]=max(dfs(i+,j),dfs(i+,j+))+a[i][j];
return dp[i][j];
}
int main(){
while(~scanf("%d",&n)){
for(int i=;i<=n;i++){
for(int j=;j<=i;j++){
scanf("%d",&a[i][j]);
}
}
mt(dp,-);
printf("%d\n",dfs(,));
}
return ;
}

自底向上的推法,那dp i j 就表示i j 这个位置能获得的最大值, 然后dp i j 可以推向两个状态,分别是 dp i-1 j 和 dp i-1 j-1.  这是用当前状态去推能到达的所有状态的写法。

 #include<cstdio>
#include<cstring>
#include<algorithm>
#define mt(a,b) memset(a,b,sizeof(a))
using namespace std;
const int M=;
int a[M][M],dp[M][M];
int main(){
int n;
while(~scanf("%d",&n)){
for(int i=;i<=n;i++){
for(int j=;j<=i;j++){
scanf("%d",&a[i][j]);
}
}
mt(dp,);
for(int i=n+;i>=;i--){
for(int j=;j<=n;j++){
dp[i-][j]=max(dp[i-][j],dp[i][j]+a[i-][j]);
dp[i-][j-]=max(dp[i-][j-],dp[i][j]+a[i-][j-]);
}
}
printf("%d\n",dp[][]);
}
return ;
}

这是用所有能到达的状态推当前状态的写法,并且空间优化了一下,省去了输入的数组。

 #include<cstdio>
#include<algorithm>
using namespace std;
const int M=;
int dp[M][M];
int main(){
int n;
while(~scanf("%d",&n)){
for(int i=;i<=n;i++){
for(int j=;j<=i;j++){
scanf("%d",&dp[i][j]);
}
}
for(int i=n-;i>=;i--){
for(int j=;j<=i;j++){
dp[i][j]=max(dp[i+][j],dp[i+][j+])+dp[i][j];
}
}
printf("%d\n",dp[][]);
}
return ;
}

最长上升子序列  http://bailian.openjudge.cn/practice/2757/

记忆化搜索

 #include<cstdio>
#include<algorithm>
using namespace std;
const int M=;
int n,a[M],dp[M];
int dfs(int i){
if(~dp[i]) return dp[i];
dp[i]=;
for(int j=i+;j<=n;j++){
if(a[i]<a[j]){
dp[i]=max(dp[i],dfs(j)+);
}
}
return dp[i];
}
int main(){
while(~scanf("%d",&n)){
for(int i=;i<=n;i++){
scanf("%d",&a[i]);
dp[i]=-;
}
int ans=;
for(int i=;i<=n;i++){
ans=max(ans,dfs(i));
}
printf("%d\n",ans);
}
return ;
}

用dp【i】表示以 i 为结尾的最长上升子序列的长度,可以得到它可以由前面所有值比他小的dp +1推过来。这是当前状态由其他所有能推过来的状态更新的写法。

 #include<cstdio>
#include<algorithm>
using namespace std;
const int M=;
int a[M],dp[M];
int main(){
int n;
while(~scanf("%d",&n)){
for(int i=;i<=n;i++){
scanf("%d",&a[i]);
dp[i]=;
}
int ans=;
for(int i=;i<=n;i++){
for(int j=;j<=i;j++){
if(a[j]<a[i]){
dp[i]=max(dp[i],dp[j]+);
}
}
ans=max(ans,dp[i]);
}
printf("%d\n",ans);
}
return ;
}

还是用dp【i】表示以 i 为结尾的最长上升子序列的长度,由当前状态去更新其他所有能更新的状态的写法。

 #include<cstdio>
#include<algorithm>
using namespace std;
const int M=;
int a[M],dp[M];
int main(){
int n;
while(~scanf("%d",&n)){
for(int i=;i<=n;i++){
scanf("%d",&a[i]);
dp[i]=;
}
for(int i=;i<=n;i++){
for(int j=i+;j<=n;j++){
if(a[i]<a[j]){
dp[j]=max(dp[j],dp[i]+);
}
}
}
int ans=;
for(int i=;i<=n;i++){
ans=max(ans,dp[i]);
}
printf("%d\n",ans);
}
return ;
}

Common Subsequence http://poj.org/problem?id=1458

用dp i j 表示a串以 i 结尾  b串 以 j 结尾的最长公共子序列长度,这个是当前状态通过其他所有状态推来的写法。

 #include<cstdio>
#include<cstring>
#include<algorithm>
#define mt(a,b) memset(a,b,sizeof(a))
using namespace std;
const int M=;
char a[M],b[M];
int dp[M][M];
int main(){
while(~scanf("%s%s",a,b)){
mt(dp,);
int n=strlen(a);
int m=strlen(b);
for(int i=;i<=n;i++){
for(int j=;j<=m;j++){
if(a[i-]==b[j-]){
dp[i][j]=max(dp[i][j],dp[i-][j-]+);
}
else{
dp[i][j]=max(dp[i-][j],dp[i][j-]);
}
}
}
printf("%d\n",dp[n][m]);
}
return ;
}

2755:神奇的口袋 http://bailian.openjudge.cn/practice/2755/

二进制枚举,暴力。

 #include<cstdio>
const int M=;
int a[M];
int main(){
int n;
while(~scanf("%d",&n)){
for(int i=;i<n;i++){
scanf("%d",&a[i]);
}
int all=<<n,ans=;
for(int i=;i<all;i++){
int sum=;
for(int j=;j<n;j++){
if((i>>j)&) sum+=a[j];
}
if(sum==) ans++;
}
printf("%d\n",ans);
}
return ;
}

dfs枚举,暴力

 #include<cstdio>
const int M=;
int a[M],ans,n;
bool use[M];
void dfs(int t){
if(t==n){
int sum=;
for(int i=;i<n;i++){
if(use[i]) sum+=a[i];
}
if(sum==) ans++;
return ;
}
use[t]=true;
dfs(t+);
use[t]=false;
dfs(t+);
}
int main(){
while(~scanf("%d",&n)){
for(int i=;i<n;i++){
scanf("%d",&a[i]);
}
ans=;
dfs();
printf("%d\n",ans);
}
return ;
}

dfs直接找解,递归,不用递归sum,k-1,用了递归sum-ak,k-1

 #include<cstdio>
int a[];
int dfs(int sum,int k){///return 前k个物品选和为sum的情况
if(sum==) return ;
if(k<=) return ;
return dfs(sum,k-)+dfs(sum-a[k],k-);
}
int main(){
int n;
while(~scanf("%d",&n)){
for(int i=;i<=n;i++){
scanf("%d",&a[i]);
}
printf("%d\n",dfs(,n));
}
return ;
}

dp递推的找解,定义方式和上面一种一样,dp i j 表示前 i 个 和为 j 的情况,这个是由选和不选两种推出两个转移方程。

 #include<cstdio>
#include<cstring>
#define mt(a,b) memset(a,b,sizeof(a))
int a[];
int dp[][];
int main(){
int n;
while(~scanf("%d",&n)){
for(int i=;i<=n;i++){
scanf("%d",&a[i]);
}
mt(dp,);
dp[][]=;
for(int i=;i<=n;i++){
for(int j=;j<=;j++){
dp[i][j]+=dp[i-][j];
if(j+a[i]<=)
dp[i][j+a[i]]+=dp[i-][j];
}
}
printf("%d\n",dp[n][]);
}
return ;
}

与上一dp相同,空间少了一维,我们只需知道某个和能达到的次数,所以输入一个个去更新所有的情况就行。这是由当前状态推向下一状态的写法。

 #include<cstdio>
#include<cstring>
#define mt(a,b) memset(a,b,sizeof(a))
int dp[];
int main(){
int n,a;
while(~scanf("%d",&n)){
mt(dp,);
for(int i=;i<=n;i++){
scanf("%d",&a);
for(int j=;j>=;j--){
if(dp[j]&&j+a<=){
dp[j+a]+=dp[j];
}
}
dp[a]++;
}
printf("%d\n",dp[]);
}
return ;
}

end

pku ppt some problem的更多相关文章

  1. PKU A Simple Problem with Integers (段树更新间隔总和)

    意甲冠军:一个典型的段树C,Q问题,有n的数量a[i] (1~n),C, a, b,c在[a,b]加c Q a b 求[a,b]的和. #include<cstdio> #include& ...

  2. 动态规划 is beginning。。。。。。。。。

    感觉动态规划非常模糊,怎么办呢??? 狂刷题吧!! !! ! !!! ! !!! !! ! ! ! .!! ..!.! PKU  PPt 动规解题的一般思路 1. 将原问题分解为子问题         ...

  3. 【解题报告】PKU 2826 An Easy Problem?!

    原题链接:http://poj.org/problem?id=2826 一题很蛋疼的一题.目前为止还有一个问题我没搞清楚,问题注在代码中. 题目大意: 外面下雨了,农民Johnoson的bull(?? ...

  4. PKU 3468 A Simple Problem with Integers

    题目大意: 有N,M两个数 Q 表示查询, 后面两个数a b,表示查询从a 到b计算它们的和 C 表示增加   后面三个数a,b,c 表示从a开始,一直到b,每个数都增加c 除了查询要进行输出,增加不 ...

  5. PKU 1208 The Blocks Problem(模拟+list应用)

    题目大意:原题链接 关键是正确理解题目意思 首先:介绍一下list容器的一些操作:参考链接 list<int> c1; c1.unique();              去重. c1.r ...

  6. PJOI PKU Campus 2011 B:A Problem about Tree LCA 求随意点x为根的y的父节点

    题目链接:点击打开链接 题意:给定n个点 m个询问 以下n-1行给定一棵树 m个询问 x y 问把树转成以x为根 y的父节点是谁 第一种情况lca==y那就是x的第 dep[x] - dep[y] - ...

  7. 刘汝佳黑书 pku等oj题目

    原文地址:刘汝佳黑书 pku等oj题目[转]作者:小博博Mr 一.动态规划参考资料:刘汝佳<算法艺术与信息学竞赛><算法导论> 推荐题目:http://acm.pku.edu. ...

  8. HDU——PKU题目分类

    HDU 模拟题, 枚举1002 1004 1013 1015 1017 1020 1022 1029 1031 1033 1034 1035 1036 1037 1039 1042 1047 1048 ...

  9. BZOJ 2301 Problem b

    AC通道:http://www.lydsy.com/JudgeOnline/problem.php?id=2301 冬令营听了莫比乌斯,这就是宋老师上课讲的例题咯[今天来实现一下] #include& ...

随机推荐

  1. 内核 current宏解析

    Technorati 标签: current thread_info      在内核中,可以通过current宏来获得当前执行进程的task_struct指针.现在来简要分析以下:      最原始 ...

  2. OOA、OOD、OOP

      复习 OOA.OOD.OOP OOA Object-Oriented Analysis:面向对象分析方法 是在一个系统的开发过程中进行了系统业务调查以后,按照面向对象的思想来分析问题.OOA与结构 ...

  3. 《shell脚本if..then..elif..then.if语句的总结》

    第一种: #!/bin/bash service vsftpd start &> /dev/null if [ $? -eq 0 ] then echo "ftp is sta ...

  4. ROS

    1 SSH 为什么我用 ssh 用户名 就不行,用 ssh xxx.xxx.xxx.xxx -l 用户名 就可以了呢 2 SCP 传送文件到另一个IP   用法: scp xxx  root@xx.x ...

  5. 基于CSS3新属性Animation及transform实现类似翻书效果

    注:本实例JS部分均以原生JS编写,不善用原生JS的,可用jQuery等对三方框架改写 先上效果图:(样式有点丑,可以忽略一下下,效果出来了就好,后期加到其他项目中方便更改0.0) 类似翻书效果,原本 ...

  6. PHP类的自动载入机制

    php的自动加载: 在php5以前,我们要用某个类或类的方法,那必须include或者require,之后才能使用,每次用一个类,都需要写一条include,麻烦 php作者想简单点,最好能引用一个类 ...

  7. WINDOWS下PHP 的pear DB的安装(本地环境:PHP5.4.15+Apache+mysql)

    因为需要安装phpunit,要先装pear,网上的教程大多数是以双击go-pear.bat开始,但是我安装的php文件夹里压根没有这个文件. 经过几次搜索之后终于找到了办法. 解决步骤如下: 1.下载 ...

  8. 扩展 delphi 线程 使之传递参数.

    新delphi的线程TThread有了CreateAnonymousThread方法,如果再为它加一个可传递的参数不就更好了吗?代码如下: TAnonymousThreadX<T> = c ...

  9. springMVC之事务配置(问题来源:为什么数据保存不了)

    参考文章:http://www.cnblogs.com/leiOOlei/p/3725911.html 自己的亲身体会,来源问题this.sessionFactory.getCurrentSessio ...

  10. Keil uVision4 代码编辑器中文字符乱码问题

    MDK-ARM 使用中一直有个很纠结的问题,中文字符支持不好. 比如写代码注释,使用中文删除字符就会只删除一半问题.复制粘贴代码中间有中文就会出现乱码问题. 想过换IAR,新学个IDE也麻烦,上面的问 ...