您的位置:首页 > 其它

动态规划练习(1)

2013-03-02 15:19 162 查看
#include<stdlib.h>
#include<stdio.h>
#define MAX 310
//http://blog.csdn.net/disappearedgod/article/details/8628975
int arr[MAX][MAX];

int main(){
int i=1,j=1;
int n =0;
scanf("%d",&n);
for(i=1;i <= n;i++){
for(j=1; j<= i;j++){
scanf("%d",&arr[i][j]);
}
}
for(i=n;i>1;i--)
{
for(j=0;j<=i-1;j++){
int a = arr[i][j]+ arr[i-1][j];
int b = arr[i][j+1]+ arr[i-1][j];
if(a>b)
arr[i-1][j]=a;
else
arr[i-1][j]=b;
}
}
int res = arr[1][1];
printf("%d",res);

//system("pause");
return 0;
}


转载请注明:From:http://blog.csdn.net/disappearedgod/article/details/8628975

例题:数字三角形(ai2760)

问题描述

7

3 8

8 1 0

2 7 4 4

4 5 2 6 5

上图给出了一个数字三角形。从三角形的顶部到底部有很多条不同的路径。对于每条路径,把路径上面的数加起来可以得到一个和,和最大的路径称为最佳路径。你的任务就是求出最佳路径上的数字之和。

注意:路径上的每一步只能从一个数走到下一层上和它最近的左边的数或者右边的数。输入数据

输入的第一行是一个整数N (1 < N <= 100),给出三角形的行数。下面的N 行给出数字三角形。数字三角形上的数的范围都在0 和100 之间。

输出要求

输出最大的和。

输入样例

5

7

3 8

8 1 0

2 7 4 4

4 5 2 6 5

输出样例

30

193

自己的想法:对于这样一个输入

7 ---第一层

| \

3 8 ---第二层

| \ | \

8 1 0 ---第三层

| \ | \ | \

2 7 4 4 ---第四层

| \ | \ | \| \

4 5 2 6 5 ---第五层

最开始的想法是从后面想到前面,我们选择的最佳路径是上一步的最佳加上现在。

对于迭代法来说,最多的是的想法是a1 = C; a (n)=f(a(n-1)) (n>1); 或者是a(n) = C, a(n-1)=f(a(n))(令n>0);我最先的想法是从an出发,当n==1时候返回值,每n-1的数是由第n层数的同一列(j)和下一列(j+1) 中的最大值产生的。

例如我们从第五层开始做

-------------------------------------------------分界线-----------------------------------------------------------

7 ---第一层
/ \

3 8 ---第二层

/ \ / \
8 1 0 ---第三层
/ \ / \ / \

2 7 4 4 ---第四层
MAX(2+4/5) MAX(7+5/2) MAX(4+2/6) MAX(4+6/5)

/ \ / \ / \ / \

4 5 2 6 5 ---第五层
-------------------------------------------------分界线-----------------------------------------------------------

7 ---第一层
/ \

3 8 ---第二层

/ \ / \
8 1 0 ---第三层
/ \ / \ / \

7 12 10 10 ---第四层
MAX(2+4/5) MAX(7+5/2) MAX(4+2/6) MAX(4+6/5)
/ \ / \ / \ / \

4 5 2 6 5 ---第五层
-------------------------------------------------分界线-----------------------------------------------------------

7 ---第一层
/ \

3 8 ---第二层
/ \ / \
8 1 0 ---第三层
MAX(8+7/12) MAX(1+12/10) MAX(0+10/10)
/ \ / \ / \

7 12 10 10 ---第四层
MAX(2+4/5) MAX(7+5/2) MAX(4+2/6) MAX(4+6/5)
/ \ / \ / \ / \

4 5 2 6 5 ---第五层
-------------------------------------------------分界线-----------------------------------------------------------

7 ---第一层
/ \

3 8 ---第二层
/ \ / \
20 13 10 ---第三层
MAX(8+7/12) MAX(1+12/10) MAX(0+10/10)
/ \ / \ / \

7 12 10 10 ---第四层
MAX(2+4/5) MAX(7+5/2) MAX(4+2/6) MAX(4+6/5)
/ \ / \ / \ / \

4 5 2 6 5 ---第五层
-------------------------------------------------分界线-----------------------------------------------------------

7 ---第一层
/ \

3 8 ---第二层
MAX(3+20/13) MAX(8+13/10)

/ \ / \
20 13 10 ---第三层
MAX(8+7/12) MAX(1+12/10) MAX(0+10/10)
/ \ / \ / \

7 12 10 10 ---第四层
MAX(2+4/5) MAX(7+5/2) MAX(4+2/6) MAX(4+6/5)
/ \ / \ / \ / \

4 5 2 6 5 ---第五层
-------------------------------------------------分界线-----------------------------------------------------------

7 ---第一层
/ \

23 31 ---第二层
MAX(3+20/13) MAX(8+13/10)

/ \ / \
20 13 10 ---第三层
MAX(8+7/12) MAX(1+12/10) MAX(0+10/10)
/ \ / \ / \

7 12 10 10 ---第四层
MAX(2+4/5) MAX(7+5/2) MAX(4+2/6) MAX(4+6/5)
/ \ / \ / \ / \

4 5 2 6 5 ---第五层
-------------------------------------------------分界线-----------------------------------------------------------

7 ---第一层
MAX(7+23/31)

/ \

23 31 ---第二层
MAX(3+20/13) MAX(8+13/10)

/ \ / \
20 13 10 ---第三层
MAX(8+7/12) MAX(1+12/10) MAX(0+10/10)
/ \ / \ / \

7 12 10 10 ---第四层
MAX(2+4/5) MAX(7+5/2) MAX(4+2/6) MAX(4+6/5)
/ \ / \ / \ / \

4 5 2 6 5 ---第五层
-------------------------------------------------分界线-----------------------------------------------------------

38 ---第一层
MAX(7+23/31)

/ \

23 31 ---第二层
MAX(3+20/13) MAX(8+13/10)

/ \ / \
20 13 10 ---第三层
MAX(8+7/12) MAX(1+12/10) MAX(0+10/10)
/ \ / \ / \

7 12 10 10 ---第四层
MAX(2+4/5) MAX(7+5/2) MAX(4+2/6) MAX(4+6/5)
/ \ / \ / \ / \

4 5 2 6 5 ---第五层
-------------------------------------------------分界线-----------------------------------------------------------

#include<stdlib.h>
#include<stdio.h>
#define MAX 310

int BestChoise(int n,int arr[MAX][MAX]){
//end
int i = 0,j=0;
for(i=n;i>0;i--)
for(j=0;j<=i-1;j++){
if(i == 1)
return arr[1][1];
int a = arr[i][j]+ arr[i-1][j];
int b = arr[i][j+1]+ arr[i-1][j];
a>b? arr[i-1][j]=a:arr[i-1][j]=b;
}

//int a = BestChoise(i+1,j,n,arr);
//int b = BestChoise(i+1,j+1,n,arr);
// a>b? arr[i][j]+=a:arr[i][j]+=b;
}
int main(){
int a[MAX][MAX];
int i=1,j=1;
int n =0;
while(scanf("%d",&n)){
for(i=1;i <= n;i++)
for(j=1; j<= i;j++)
scanf("%d",&a[i][j]);
/*
for(i=1;i<=n;i++){
for(j=1;j<=i;j++){
printf("%d  ",a[i][j]);
if(j==i)
printf("\n");
}
}
*/
printf("%d",BestChoise(n,a));
}
system("pause");
return 0;
}


状态: Output
Limit Exceeded


基本信息

题目:2760 内存:256kB
时间:1970ms

-------------------------------------------------分界线-----------------------------------------------------------

看了一下解题思路

1.递归的本源思想

这道题目可以用递归的方法解决。基本思路是:

以D( r, j)表示第r 行第j 个数字(r,j 都从1 开始算),以MaxSum(r, j) 代表从第r 行

的第j 个数字到底边的最佳路径的数字之和,则本题是要求MaxSum(1, 1) 。

从某个D(r, j)出发,显然下一步只能走D(r+1, j)或者D(r+1, j+1)。如果走D(r+1, j),那

么得到的MaxSum(r, j)就是MaxSum(r+1, j) + D(r, j);如果走D(r+1, j+1),那么得到的MaxSum

(r, j)就是MaxSum(r+1, j+1) + D(r, j)。所以,选择往哪里走,就看MaxSum(r+1, j)和MaxSum

(r+1, j+1)哪个更大了。

对比于迭代法的代码

#include<stdlib.h>
#include<stdio.h>
#define MAX 310
int BestChoise(int i,int j,int n,int arr[MAX][MAX]){
//end
if(i == n)
return arr[i][i];

//int a = arr[i+1][j]+ arr[i][j];
//int b = arr[i+1][j+1]+ arr[i][j];
//a>b? arr[i][j]=a:arr[i][j]=b;
int a = BestChoise(i+1,j,n,arr);
int b = BestChoise(i+1,j+1,n,arr);
a>b? arr[i][j]+=a:arr[i][j]+=b;
return arr[i][j];
}
int main(){
int a[MAX][MAX];
int i=1,j=1;
int n =0;
while(scanf("%d",&n)){
for(i=1;i <= n;i++)
for(j=1; j<= i;j++)
scanf("%d",&a[i][j]);
//   for(i=1;i<n;i++)
//         for(j=1;j<=i;j++)
//          printf("%d",BestChoise(1,1,n,a));
printf("%d",BestChoise(1,1,n,a));
}
system("pause");
return 0;
}



基本信息

#:1891452
题目:2760
提交人:disappearedgod
内存:256kB
时间:1640ms
语言:G++
提交时间:2013-03-05 12:04:15

上述想法在时间复杂度上很大,递归改变成动态规划。而第一次的代码属于动态规划,但是仍然超时。

发现函数调用可以不用存在,并且最重要的是,while语句是多余的,因为没有说要多次输入。所以改成

#include<stdlib.h>
#include<stdio.h>
#define MAX 310
//http://blog.csdn.net/disappearedgod/article/details/8628975
int arr[MAX][MAX];

int main(){
int i=1,j=1;
int n =0;
scanf("%d",&n);
for(i=1;i <= n;i++){
for(j=1; j<= i;j++){
scanf("%d",&arr[i][j]);
}
}
for(i=n;i>1;i--)
{
for(j=0;j<=i-1;j++){
int a = arr[i][j]+ arr[i-1][j];
int b = arr[i][j+1]+ arr[i-1][j];
if(a>b)
arr[i-1][j]=a;
else
arr[i-1][j]=b;
}
}
int res = arr[1][1];
printf("%d",res);

//system("pause");
return 0;
}


-------------------------------------------------分界线-----------------------------------------------------------

注意

#include<stdlib.h>
#include<stdio.h>
#define MAX 310
//http://blog.csdn.net/disappearedgod/article/details/8628975
int arr[MAX][MAX];

int main(){
//int a[MAX][MAX];
int i=1,j=1;
int n =0;
scanf("%d",&n);
for(i=1;i <= n;i++){
for(j=1; j<= i;j++){
scanf("%d",&arr[i][j]);
}
}
for(i=n;i>1;i--)
{
for(j=0;j<=i-1;j++){
int a = arr[i][j]+ arr[i-1][j];
int b = arr[i][j+1]+ arr[i-1][j];
a>b? arr[i-1][j]=a:arr[i-1][j]=b;
}
}
printf("%d",arr[1][1]);

//system("pause");
return 0;
}


这个代码中的:? 对于GCC编译器来讲是错的,报错为


error: lvalue required as left operand of assignment

lvalue:左值是指可以被赋值的表达式。左值位于赋值语句的左侧与其相对的右值(rvaule)则位于赋值语句的右侧。

赋值语句都必须有一个左值和一个右值。左值必须是内存一个可存储的变量,而不能是一个常量。

所以,可以改成if else

if(a>b)
arr[i-1][j]=a;
else
arr[i-1][j]=b;
}


转载请注明:From:http://blog.csdn.net/disappearedgod/article/details/8628975
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: