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. 常用的HTML 标签二

    <marquee></marquee> 滚动的文字,也称"走马灯" 语法格式 <marquee 属性="属性值">内容< ...

  2. 模拟n步一维随机游走的情况。

    package randomWalk; import java.util.Random; import java.util.Scanner; public class RandomWalk { pub ...

  3. 安装Java EE失败,解决方案

    笔者安装Java EE(版本是java_ee_sdk-7-jdk7-windows-x64-ml.exe)时,遇到错误提示提示"Could not find the required ver ...

  4. 【NPOI】.NET EXCEL导入导出开发包

    1.导出 //工作簿HSSFWorkbook HSSFWorkbook hssfworkbook = new HSSFWorkbook(); //ISheet页 ISheet sheet1 = hss ...

  5. [转]高并发访问下避免对象缓存失效引发Dogpile效应

    避免Redis/Memcached缓存失效引发Dogpile效应 Redis/Memcached高并发访问下的缓存失效时可能产生Dogpile效应(Cache Stampede效应). 推荐阅读:高并 ...

  6. select的onChange事件问题解决

    一.onChange事件只有在值改变时才可触发,所以必须在每一次选择时(尤其第一次)保证选择的值是改变的! 所以<select name="inv_payee" id=&qu ...

  7. JS预览图像将本地图片显示到浏览器上的代码

    js代码实现: 从file域获取本地图片url并将本地图片显示到浏览器上. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitio ...

  8. windows创建桌面快捷方式的VBA脚本

    Dim wShell, oShortcut    'Dim strDesktop$ ' 为了与VBS兼容,    Dim strDesktop    ' 这里改写一下,测试通过...    Set w ...

  9. XAML 概述二

    通过上一节我们已经对XAML有了一定的了解,这一节我们来系统的学习一下XAML. 一. 简单属性与类型转换器,属性元素: 我们已经知道 XAML是一种声明性的语言,并且XAML解析器会为每个标签创建一 ...

  10. posix 消息队列

    注意 在涉及到posix消息的函数时, gcc 编译时要加-lrt参数, 如 gcc -lrt unpipc.c mqpack.c send.c -o send gcc -lrt unpipc.c m ...