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. 另类安装系统——PE工具提取

    1. 在当前系统使用安装工具win$man打开,即pe里集成安装工具 2. 选择安装的磁盘或者分区和引导分区 3. 可以默认下一步 4. 不想更改盘符可以默认下一步 5. 最后完成开始安装部署(还需要 ...

  2. Objective-C 【This is ARC】

    ------------------------------------------- ARC的概念及原理 (1)指针分类 强指针:默认情况下,所有的指针都是强指针,关键字strong 弱指针:_ _ ...

  3. [转]基于SQL脚本将数据库表及字段提取为C#中的类

    开发时,勉不了需要使用SQL直接与数据库交互,这时对于数据库中的表名及字段名会使用的比较多.如果每使用一次都复制一个,实在蛋疼.所以就考虑将其做成const常量.但是数据库中的表和字段相当多,一个一个 ...

  4. UI4_注册登录界面

    // // ViewController.h // UI4_注册登录界面 // // Created by zhangxueming on 15/7/3. // Copyright (c) 2015年 ...

  5. Android四大组件之一:Activity

    介绍:活动是最基本的Android组件之一,在应用程序中,一个活动通常就是一个用户界面,每一个活动都被实现为一个独立的类,并且从活动几类中继承, 活动类将会显示由View控件组成的用户接口,并对时间E ...

  6. 《搭建更新DNS集群服务》RHEL6

    DNS服务器的更新: 一听就知道不止一台的DNS服务器,要是一台也用不着更新对吧?一般都是DNS集群. 一台DNS更新了,添加一条数据,下面的都要跟着它变. 主DNS服务器的配置 首先先配置DNS服务 ...

  7. Ubuntu系统下允许Apache的mod_rewrite功能

    首先,使能apache的rewirte模块,在shell里输入下边的命令: sudo a2enmod rewrite 然后重启一下webserver使更改生效 sudo service apache2 ...

  8. 百度云盘demo

  9. php判断ip黑名单程序代码

    学校的新闻系统要求有些新闻只开放校内ip浏览,于是重写了一个代码来实现此功能,实现后的结果是,只要把允许访问的ip列入ip.txt这个文件中即可,同时支持c类ip,例如: ip.txt192.1682 ...

  10. 一,XAML基础

    RuntimeNameProperty特性:为什么<Grid x:Name="grid1"></Grid>等价于<Grid Name="gr ...