ACM 191. 取数字问题(dp)

来源:互联网 发布:淘宝充值到空号怎么办 编辑:程序博客网 时间:2024/04/30 13:14

191. 取数字问题

★☆   输入文件:number.in   输出文件:number.out   简单对比
时间限制:1 s   内存限制:128 MB

【问题描述】
     给定 M*N 的矩阵,其中的每个元素都是 -10 到 10 之间的整数。你的任务是从左上角( 1 , 1 )走到右下角( M , N ),每一步只能向右或向下,并且不能走出矩阵的范围。你所经过的方格里面的数字都必须被选取,请找出一条最合适的道路,使得在路上被选取的数字之和是尽可能小的正整数。

【输入格式】 
    第一行两个整数 M , N ,( 2<=M,N<=20 ),分别表示矩阵的行和列的数目。

接下来的 M 行,每行包括 N 个整数,就是矩阵中的每一行的 N 个元素。

【输出格式】 
   仅一行一个整数,表示所选道路上数字之和所能达到的最小的正整数。如果不能达到任何正整数就输出 -1 。 
 

【输入输出样例】
 
输入: 
number.in
2 2
0 2
1 0
输出:
number.out
1


动态规划

dp(i,j,l)为数l能否在i,j处得到

#include <iostream>#include <cstring>#include <cstdio>using namespace std;#define INF 99999999#define MAX_N 21#define dp(y,x,z) dp[y][x][z+200]int M,N;int lim;int map[MAX_N][MAX_N];bool dp[MAX_N][MAX_N][MAX_N*MAX_N];int main(){freopen("number.in","r",stdin);freopen("number.out","w",stdout);scanf("%d%d",&M,&N);for(int i=1;i<=M;i++)for(int j=1;j<=N;j++){scanf("%d",&map[i][j]);}lim=200;dp(0,1,0)=true;for(int i=1;i<=M;i++){for(int j=1;j<=N;j++){for(int k=-lim;k<=lim;k++){int l=k-map[i][j];dp(i,j,k)=dp(i-1,j,l) | dp(i,j-1,l);}}}int ans=-1;for(int k=1;k<=lim;k++){if(dp(M,N,k)){ans=k;break;}}printf("%d\n",ans);return 0;}


0 0
原创粉丝点击