DP的简单应用

Problem A:简单的图形覆盖

Time Limit:1000MS  Memory Limit:65536K
Total Submit:201 Accepted:104

Description

有一个2*n的方格,要用若干个1*2的模块覆盖,模块可以横放,也可以竖放.问对于给定的n(n<=100),有多少种不同的覆盖方法.

Input

有多个测试用例,每个用例占一行,为一个正整数n

Output

对于每个测试用例,输出一行相应的结果

Sample Input

9

11

Sample Output

55

144

分析:

f(n)={ 1  n=1

     2  n=2

   f(n-1)+f(n-2) n>2

}

 1 #include<stdio.h>
 2 int A[101];
 3 int main()
 4 {
 5    int n,i;
 6    while(scanf("%d",&n)!=EOF)
 7    {
 8        A[0]=1;A[1]=1;
 9        if(n==1||n==0)  printf("%d\n",A[0]);
10        else
11        {
12        for(i=2;i<n;i++)
13            A[i]=A[i-1]+A[i-2];
14        printf("%d\n",A[i]);
15        }
16    }
17    return 0;
18 }

递归解决

 1 #include <stdio.h>
 2 #include <string.h>
 3 int A[101];
 4 int f(int n)
 5 {
 6     memset(A,-1,sizeof(A));
 7     if (A[n]!=-1) return A[n];
 8     if(n==0||n==1)
 9     {
10         A[n]=1;
11     }
12     else
13     {
14         A[n]=f(n-1)+f(n-2);
15
16     }
17     return A[n];
18 }
19 int main()
20 {
21     int n;
22     while(scanf("%d",&n)!=EOF)
23    {
24        printf("%d\n",f(n));
25    }
26    return 0;
27 }

Problem B:最大子段和

Time Limit:1000MS  Memory Limit:65536K
Total Submit:574 Accepted:299

Description

有一组数,如-2 5 4 -3 7 的最大子段和是13, 是从5到7.

Input

第一行输入一个n(1〈 N〈=100 ) 表示这一组数有多长,第二行是N个数. 
测试案例有多个,n=0时结束.

Output

输出这一组数的最大子段和.

Sample Input

5

-2 5 4 -3 7

10

9 -3 8 -28 98 -30 -20 50 -24 10

0

Sample Output

13

98

分析:

A


-2


5


4


-3


7

B 表示A0~Ai数段中包含第i个元素的最大子段和


-2


5


9


6


13

B[i]={

  A[i]   i=0;

  max{ B[i-1]+A[i] , A[i] } i>0;

}

 1 #include<stdio.h>
 2 int A[101];
 3 int B[101];
 4 int main()
 5 {
 6    int n,i,max;
 7    scanf("%d",&n);
 8    while(n!=0)
 9    {
10        for(i=0;i<n;i++)
11            scanf("%d",&A[i]);
12        B[0]=A[0];
13        for(i=0;i<n;i++)
14            if(B[i-1]<0) B[i]=A[i];
15            else
16                B[i]=B[i-1]+A[i];
17 /*       max=B[0];
18        for(i=1;i<n;i++) if(max<B[i]) max=B[i];
19        printf("%d\n",max);
20        scanf("%d",&n);*/
21 printf("%d\n",B[n-1]);
22
23    }
24    return 0;
25 }

Problem C:最长公共子序列

Time Limit:1000MS  Memory Limit:65536K
Total Submit:164 Accepted:99

Description

我们称序列Z=是序列X=的子序列当且仅当存在严格上升的序列,使得对j=1,2,...k,有Xij=Zj.比如Z=<a,b,f,c>是X=<a,b,c,f,b,c>的子序列.现在给出两个序列X和Y,任务是找到X和Y的最大公共子序列,也就是说要找到一个最长的序列Z,使得Z既是X的子序列也是Y的子序列.

Input

输入包括多组测试数据.每组数据包括一行,给出两个长度不超过200的字符串,表示两个序列.两个字符串之间由若干个空格9开.

Output

对每组输入数据,输出一行,给出两个序列的最大公共子序列的长度.

Sample Input

abcfbc  abfcab

programming contest

abcd mnp

Sample Output

4

2

0

分析

Z[i][j]= {

      0  i=0或j=0;

      Z[i-1][j-1]+1  X[i]=Y[j];

      max{ Z[i-1][j] , Z[i][j-1] }  X[i]!=Y[j]

}


下标


0


1


2


3


4


5


6


Z[i][j]


a


b


c


f


b


c


0


0


0


0


0


0


0


0


1


a


0


1


1


1


1


1


1


2


b


0


1


2


2


2


2


2


3


f


0


1


2


2


3


3


3


4


c


0


1


2


3


3


3


4


5


a


0


1


2


3


3


3


4


6


b


0


1


2


3


3


4


4

X,Y下标从0开始,Z[i][j] 下标有效的从1开始

 1 #include<stdio.h>
 2 #include<string.h>
 3 char x[201];
 4 char y[201];
 5 int z[200][200];
 6 int main()
 7 {
 8    int i,j,s,t,max;
 9    while(scanf("%s%s",x,y)!=EOF)
10    {
11        s=strlen(x);t=strlen(y);
12        for(i=0;i<s;i++)
13            z[i][0]=0;
14         for(j=0;j<t;j++)
15            z[0][j]=0;
16         for(i=1;i<=s;i++)
17             for(j=1;j<=t;j++)
18             {
19                 if(x[i-1]==y[j-1]) z[i][j]=z[i-1][j-1]+1;
20                 else
21                 {
22                     if(z[i-1][j]>=z[i][j-1]) z[i][j]=z[i-1][j];
23                     else   z[i][j]=z[i][j-1];
24                 }
25             }
26 /*        max=z[0][0];
27         for(i=0;i<=s;i++)
28             for(j=0;j<=t;j++)
29                 if(z[i][j]>max) max=z[i][j];*/
30         printf("%d\n",z[s][t]);
31    }
32
33    return 0;
34 }

Problem D:最长上升子序列

Time Limit:1000MS  Memory Limit:65536K
Total Submit:456 Accepted:239

Description

一个数的序列bi,当b1<=b2<=b3..<=bn的时候,称这个序列是上升的。对于给定的一个序列(A1,A2,....,AN),可以得到一些上升的子序列(AI1,AI2,....AIK,这里1<=I1<=I2<=....<=IK<=N,比如,对于序列(1,7,3,5,9,4,8),有它的一些上升子序列,如(1,7),(3,4,8)等.这些子序列中最长的长度是4,比如子序列(1,3,5,8). 
你的任务就是对于给定的序列,求出最长上升子序列的长度.

Input

输入有多个案例,每个案例占两行: 
第一行是序列的长度N(1<=N<=1000).第二行给出序列中的N个整数,这些整数的取值范围都在0到10000.

Output

最长上升子序列的长度.

Sample Input

7

1 7 3 5 9 4 8

2

1036 3

Sample Output

4

1

分析

设置b[N],b[i]表示序列的第1个数到第i个数(保留第i个数)的最长上升子序列的长度。

b[i]=max(b[j])+1(a[j]<a[i],1<=j<=i<=n)

如果a[i]最小,则b[i]=1


A


1


7


3


5


9


4


8


B


1


2


2


3


4


3


4

 1 #include<stdio.h>
 2 int A[100],B[100];
 3 int main()
 4 {
 5     int n,i,j,max;
 6     while(scanf("%d",&n)!=EOF)
 7     {
 8         for(i=0;i<n;i++)
 9             scanf("%d",&A[i]);
10         B[0]=1;
11         for(i=1;i<n;i++)
12         {
13             max=0;
14             for(j=0;j<i;j++)
15                 if(A[j]<A[i]&&B[j]>max) max=B[j];
16             B[i]= max+1;
17
18         }
19         max=B[0];
20         for(i=1;i<n;i++)
21             if(max<B[i]) max=B[i];
22         printf("%d\n",max);
23     }
24     return 0;
25 }

时间: 2024-10-21 10:09:05

DP的简单应用的相关文章

dp优化简单总结

1.二分优化 (使用二分查找优化查找效率) 典型例题:LIS dp[i]保存长度为 i 的上升子序列中最小的结尾,可以用二分查找优化到nlogn 2.数学优化 (通过数学结论减少状态数) 例题1:hdu4623   题解 例题2:usaco4.11 题解 大意是求10个数及其倍数最大不能表示的数 有数论结论证明对于互质的p,q,最大不能表示的数不会超过p*q,所以这个题就成了有上限(256*256)的问题了,在上限内跑背包即可. 3.矩阵优化(通过矩阵快速幂加速状态转移) ...... 4.单调

codeforce1029B B. Creating the Contest(简单dp,简单版单调栈)

B. Creating the Contest time limit per test 1 second memory limit per test 256 megabytes input standard input output standard output You are given a problemset consisting of nn problems. The difficulty of the ii-th problem is aiai. It is guaranteed t

dp状态压缩

dp状态压缩 动态规划本来就很抽象,状态的设定和状态的转移都不好把握,而状态压缩的动态规划解决的就是那种状态很多,不容易用一般的方法表示的动态规划问题,这个就更加的难于把握了.难点在于以下几个方面:状态怎么压缩?压缩后怎么表示?怎么转移?是否具有最优子结构?是否满足后效性?涉及到一些位运算的操作,虽然比较抽象,但本质还是动态规划.找准动态规划几个方面的问题,深刻理解动态规划的原理,开动脑筋思考问题.这才是掌握动态规划的关键. 动态规划最关键的要处理的问题就是位运算的操作,容易出错,状态的设计也直

poj 3254 Corn Fields(状态压缩dp)

Description Farmer John has purchased a lush new rectangular pasture composed of M by N (1 ≤ M ≤ 12; 1 ≤ N ≤ 12) square parcels. He wants to grow some yummy corn for the cows on a number of squares. Regrettably, some of the squares are infertile and

hdu5179(数位dp)

传送门:beautiful number 题意:令 A=∑ni=1ai?10n?i(1≤ai≤9)(n为A的位数).若A为“漂亮的数”当且仅当对于任意1≤i<n满足a[i]≥a[i+1]且对于任意1≤i≤n,i<j≤n,满足a[i] mod a[j]=0(例如931是一个“漂亮的数”而87不是),求在区间[L,R](包含L和R)里“漂亮的数”的个数. 分析:数位dp较为简单,dp[pos][pre]表示还有pos位且前一位数字是pre非限制条件下为漂亮数字的个数. #pragma commen

大话设计模式第八章之简单工厂模式

简单工厂模式 工厂方法模式 package com.dp.factory; interface IFactory { Calculator CreateCalculator(); } class AddFactory implements IFactory { @Override public Calculator CreateCalculator() { return new CalculatorAdd(); } } class SubFactory implements IFactory {

DP基础

DP基础 简单dp 背包问题 记忆化搜索 简单dp 数字三角形 给一个数字构成的三角形,求从顶端走到底部的一条路径,使得路径上的和最大(或者最小). 1 2 3 6 5 4 Example_1 7 3 8 8 1 0 5 2 6 100000 Example_2 根据Example_2可以知道贪心显然是不正确的. 可以看出,除了两边的点以外,每个点可以上一层的两个位置之一到达当前点. 如果我们知道上一层的从顶端到达两个位置的最大路径值,那么对于当前点来说,必然选择较大的那个位置转移过来,也就得到

android中dip、dp、px、sp和屏幕密度

1. dip: device independent pixels(设备独立像素). 不同设备有不同的显示效果,这个和设备硬件有关,一般我们为了支持WVGA.HVGA和QVGA 推荐使用这    这个,不依赖像素.     这里要特别注意dip与屏幕密度有关,而屏幕密度又与具体的硬件有关,硬件设置不正确,有可能导致dip不能正常显示.在屏幕密度为160的显示屏上,1dip=1px,有时候可能你的屏幕分辨率很大如480*800,但是屏幕密度没有正确设置比如说还是160,那么这个时候凡是使用dip的

【期望DP】

[总览] [期望dp] 求解达到某一目标的期望花费:因为最终的花费无从知晓(不可能从$\infty$推起),所以期望dp需要倒序求解. 设$f[i][j]$表示在$(i, j)$这个状态实现目标的期望值(相当于是差距是多少). 首先$f[n][m] = 0$,在目标状态期望值为0.然后$f = (\sum f' × p) + w $,$f'$为上一状态(距离目标更近的那个,倒序),$p$为从$f$转移到$f'$的概率(则从$f'$转移回$f$的概率也为$p$),w为转移的花费. 最后输出初始位置