【2007年提高组3】矩阵取数游戏

来源:互联网 发布:厂家寻找淘宝卖家合作 编辑:程序博客网 时间:2024/06/05 03:22

【2007年提高组3】矩阵取数游戏

Time Limit:10000MS  Memory Limit:65536K
Total Submit:10 Accepted:3 
Case Time Limit:1000MS

Description

问题描述 
帅帅经常跟同学玩一个矩阵取数游戏,对于一个给定的n*m的矩阵,矩阵中每个元素Aij为非负整数。游戏规则如下: 
1.每次取数时须从每行各去走一个元素,共N个.M次后取完矩阵所有元素; 
2.每次取数都是一个得分值,为每行取数的得分之和,每行取数的得分=被取走的元素值*2(2 
右上角有个i),其中i表示第i次取数(从1开始编号) 
3.每次取走的各个元素只能是该原素所在行的行首或行尾. 
4.游戏结束总得分为M次取数得分之和

Input

输入文件game.in包括N+1行 
第1行为两个用空格隔开的整数N和M 
第2-N+1行为N*M矩阵,其中每行有M个用单个空格隔开的非负整数

Output

输出文件game.out仅包含1行,为一个整数,即输入矩阵取数后的最大得分.

Sample Input

2 3 1 2 3 3 4 2

Sample Output

82

Hint

输入输出样例2 
Game.in 
1 4 
4 5 0 5 
Game.out 
122 
输入输出样例3 
Game.in 
2 10 
96 56 54 46 86 12 23 88 80 43 
16 95 18 29 30 53 88 83 64 67 
Game.out 
316994 
限制 
60%的数据满足:1<=n,m<=30,答案不超过10^16 
100%的数据满足:1<=n,m<=80,0<=Aij<=1000

Source

稍微分析这题时可以发现每个n行是独立的,也就是说只要求出一行的最大得分,其他行的求法是一样的。很容易看出是要用动态规划,一开始我是这样想的,逆向从最后一次的状态逐渐向第一次转移。最后一次的状态很容易写出

就是dp[1][i]=a[x][i] x代表要求的行),

倒数第二次就是在最后一次的基础上向两边扩充,但是发现在m=80的时候 空间可能会达到2^40次方。。这肯定不行的。

其实这题就是类似石子归并类的题目,但是到自己做的时候还是无法做出,看了别人的题解又勉强“才会”,不知道以后遇到类是的还会不会。。。

这题的动态转移方程其实就dp[L][R]=2*max(dp[L+1][R]+a[x][L],dp[L][R-1]+a[x][R]),其实就是在L-R之间最大得分。每次可以取最左边和最右边两种情况,其实感觉就是分治。在我想的思路上加上分治。

由于结果很大。还要用到高精度。所以我用JAVA大整数做的(偷懒点)。

下面是AC代码:

import java.util.*;import java.math.*;public class Main {/** * @param args */ static int [][] a  = new int [100][100]; static BigInteger [][] dp = new BigInteger [100][100]; static BigInteger max_val(BigInteger a,BigInteger b) {  if(a.max(b)==a)  return a;else  return b; } public static BigInteger solve(int i,int l,int r){if(l==r)  dp[l][r]=BigInteger.valueOf(a[i][l]).multiply(BigInteger.valueOf(2));if(dp[l][r].compareTo(BigInteger.ZERO)>=0)return dp[l][r];if(l==r)return dp[l][r];if(l+1<=r)dp[l][r]=(solve(i,l+1,r).add(BigInteger.valueOf(a[i][l]))).multiply(BigInteger.valueOf(2));if(l<=r-1)    dp[l][r]=max_val(dp[l][r],(solve(i,l,r-1).add(BigInteger.valueOf(a[i][r]))).multiply(BigInteger.valueOf(2)));//System.out.println(dp[l][r]);return dp[l][r];}public static void main(String[] args) {// TODO Auto-generated method stub\Scanner cin = new Scanner (System.in);int n=cin.nextInt(),m=cin.nextInt();BigInteger sum=BigInteger.ZERO;for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)a[i][j]=cin.nextInt();//for(i=1;i<=n;i++)//for(j=1;j<=m;j++)//System.out.println(a[i][j]);for(int i=1;i<=n;i++){for(int k=0;k<=99;k++)for(int j=0;j<=99;j++)dp[k][j]=BigInteger.valueOf(-1);solve(i,1,m);sum=sum.add(dp[1][m]);}System.out.println(sum);}}


原创粉丝点击