您的位置:首页 > 其它

DP的学习和使用

2011-03-24 22:57 127 查看
1. 如果自顶向下的程序不好设计的话,就变成自底向上的好了

/* goso : Dynamic Programming :: 数塔的问题
思想就是不断的上溯,自底向上求解
如果自顶向下求解的话非常麻烦
*/
#include <stdio.h>
#define MAX_ARRAY 0xff
main() {
int i=0,j=0,t=0;
int a[MAX_ARRAY][MAX_ARRAY] = {0};
while (scanf("%d",&t) != EOF)  // 又学到了一种用法
{
for (i=0 ; i<t ; ++i)
{
for (j=0 ; j<=i; ++j)
{
scanf("%d",&a[i][j]);
}
} // 接收完成
for (i=t-2; i>=0 ; --i)
{
for (j=0; j<=i ; ++j)
{
a[i][j] += a[i+1][j] > a[i+1][j+1] ? a[i+1][j] : a[i+1][j+1];
}
}
}
printf("%d",a[0][0]);
}


2. 如果大量的递归导致程序时间的拖延,那么就以空间换时间,记录递归的中间结果

/* 记录递归的中间结果,降低递归程序进入的次数,减少程序的时间消耗 */
#include <stdio.h>
static int e[21][21][21];
int w(int a,int b,int c) {
if (a <= 0 || b <= 0 || c <= 0) return 1;
else if(a > 20 || b > 20 || c > 20) return w(20,20,20);
else if(a < b && b < c) {
if (e[a][b][c]) return e[a][b][c];
else { e[a][b][c] = w(a,b,c-1) + w(a,b-1,c-1) - w(a,b-1,c); return e[a][b][c]; }
}
else {
if (e[a][b][c]) return e[a][b][c];
else { e[a][b][c] = w(a-1,b,c) + w(a-1,b-1,c) + w(a-1,b,c-1) - w(a-1,b-1,c-1); return e[a][b][c]; }
}
}
main() {
int a=0,b=0,c=0,res=0;
scanf("%a %b %c",&a,&b,&c);
res = w(a,b,c);
printf("%d",res);
}


3. Max sum 问题

一般人的想法是:从a[i] 的每一个i开始遍历一次数组,分别计算出每一次遍历的最大值,最后将所有的最大值对比。

程序时间复杂度为o(n*n)

使用DP,只需要 o(n) 即可

关于代码,我大概看懂了,但是没明白为什么这样就算是动态规划。。。

/* Max sum sequence */
#include <stdio.h>
#define MAX_ARRAY 0xff
main() {
int a[MAX_ARRAY] = {0};
int n=0,i=0;
int sum=0,maxsum=-9999;  // C语言中最小值那个宏叫什么来?
int start=0,end=0,tmp=0;
scanf("%d",&n);
for (;i<n;++i)
{
scanf("%d",&a[i]);  // store in array
}
for (i=0; i<n; ++i)
{
sum += a[i];
if (sum > maxsum)
{
maxsum = sum; start = tmp; end = i;
}
if (sum < 0)
{
tmp = i+1; sum = 0;
}
}
printf("%d/t%d/t%d/n",maxsum,start,end);
}


进阶的情况:线性变二维

想法降回线性

/* Max sum matrix */
/* 寻找一个方法把二维变成一维 */
#include <stdio.h>
#define MAX_ARRAY 0xff
main() {
int m=0,n=0;
int i=0,j=0,k=0,l=0;
int a[MAX_ARRAY][MAX_ARRAY] = {0};
int seed[MAX_ARRAY] = {0};
scanf("%d %d",&m,&n);
for (i=0; i<m; ++i)
{	for (j=0; j<m; ++j)
{
scanf("%d",&a[i][j]);
}
}
for (i=0; i<m; ++i)
{	for (j=i; j<m; ++j)          /// 这里的i,j都是对行进行遍历,跟平时的不同
{
for (k=0; k<n; ++k)
{
seed[k]=0;
for (l=i; l<=j; ++l)
{
seed[k] += a[l][k];
}
}
// call a procedure of 1
//save the biggest integer
}
}
}


求序列的最大上升序列(可以不连续)

/* Super Jump! Jump! Jump! */
#include <stdio.h>
#define MAX_ARRAY 0xff
main() {
int a[MAX_ARRAY] = {1,4,7,3,5,6};
int b[MAX_ARRAY] = {1};
int i=0,j=0,maxb=0,maxnum=0;
for (i=0 ; i<6 ; ++i)
{
// 找比自己小的数字中的和的最大值
maxb = 0;
for (j=0; j<i; ++j)
{
if (a[j] < a[i] && b[j] > maxb)
{
maxb = b[j];
}
}
b[i] = maxb+a[j];
if (b[i] > maxnum)
{
maxnum = b[i];
}
}
printf("%d",maxnum);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: