转载:取数字问题
取数字问题
给定M×N的矩阵,其中的每个元素都是-10到10之间的整数,你需要从左上角(1,1)走到右下角(M,N)
每次只能向右或者向下走,且不能走出矩阵的范围,你经过的方格的数字都会被选取,你需要找出一条合适的道路,这条道路满足,你走过的数字之和最小(如果最大也使一样的思路);
第一行输入两个整数M和N,接下来第M行每行输入N个整数;
输入最小和;
//分析:这是一个动态规划典型例题,首先我们从底向上分析,走到(M,N)那么可能经过(M-1,N)或者经过(M,N-1);则必须满足走到(M-1,N)或者走到(M,N-1)之前的和是最小的,以此类推,在前面几章中介绍过,动态规划相当于一个表格,将每次最优的值存在数组中,那么我可以这么想了,首先第一行所有值(1,1)的值肯定最小,如果要走过(1,2)那么(1,1)+(1,2)的值肯定最下,走第一行和走第一列都是这样的性质,那么我将可能的第一行和第一列的值都算出来,而(2,2)可以是(2,1)或者(1,2)走过来的,那么如果(1,2)+(2,2)小于(2,1)+(2,2)那么(2,2)存得值就是(1,2)+(2,2),这必然是经过(2,2)最小的值,以此类推下去,直到推到(M,N)那么(M,N)一定是最小的值
C++代码如下:
#include<iostream>
using namespace std;
int a[100][100];
int b[100][100];
void minsum(int m,int n)
{
int i,j;
b[0][0]=a[0][0];
for(i=1;i<n;i++)
b[0][i]=b[0][i-1]+a[0][i];
for(i=1;i<m;i++)
{
b[i][0]=b[i-1][0]+a[i][0];
for(j=1;j<n;j++)
{
if(b[i][j-1]+a[i][j]>b[i-1][j]+a[i][j])
b[i][j]=b[i-1][j]+a[i][j];
else
b[i][j]=b[i][j-1]+a[i][j];
}
}
}
int main()
{
int m,n;
int i,j;
while(cin>>m>>n)
{
for(i=0;i<m;i++)
{
for(j=0;j<n;j++)
cin>>a[i][j];
}
memset(b,0,sizeof(b));
minsum(m,n);
cout<<b[m-1][n-1]<<endl;
}
return 0;
}
int a[100][100];
int b[100][100];
void minsum(int m,int n)
{
int i,j;
b[0][0]=a[0][0];
for(i=1;i<n;i++)
b[0][i]=b[0][i-1]+a[0][i];
for(i=1;i<m;i++)
{
b[i][0]=b[i-1][0]+a[i][0];
for(j=1;j<n;j++)
{
if(b[i][j-1]+a[i][j]>b[i-1][j]+a[i][j])
b[i][j]=b[i-1][j]+a[i][j];
else
b[i][j]=b[i][j-1]+a[i][j];
}
}
}
int main()
{
int m,n;
int i,j;
while(cin>>m>>n)
{
for(i=0;i<m;i++)
{
for(j=0;j<n;j++)
cin>>a[i][j];
}
memset(b,0,sizeof(b));
minsum(m,n);
cout<<b[m-1][n-1]<<endl;
}
return 0;
}