动态规划练习(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
相关文章推荐
- 动态规划练习一 05:吃糖果
- 动态规划练习一 23:大盗阿福
- 动态规划练习一—13最大上升子序列
- 动态规划练习--21(三角形最佳路径问题)
- 动态规划练习——最大子矩阵
- 数据结构与算法练习-动态规划
- 动态规划练习一—14怪盗基德的滑翔翼
- 动态规划练习03:采药
- 最长递增、递减子序列(导弹拦截问题)动态规划练习
- 动态规划练习 14
- SDAU 编程练习三 动态规划和动态规划与背包问题相结合的问题
- 每周算法练习——动态规划
- 动态规划练习一 13:最大上升子序列和
- 动态规划练习一—16踩方格
- 动态规划练习04:公共子序列
- 编程练习-动态规划(矩阵乘法)
- 算法练习(7) —— 动态规划 Strange Printer
- 动态规划练习 4
- 动态规划练习一 14:怪盗基德的滑翔翼
- 动态规划练习-1(最长上升子序列)