矩阵取数

Description

帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的n·m的矩阵,矩阵中的每个元素aij据为非负整数。游戏规则如下:

  1. 每次取数时须从每行各取走一个元素,共n个。m次后取完矩阵所有的元素;
  2. 每次取走的各个元素只能是该元素所在行的行首或行尾;
  3. 每次取数都有一个得分值,为每行取数的得分之和;每行取数的得分 = 被取走的元素值*2i,其中i表示第i次取数(从1开始编号);
  4. 游戏结束总得分为m次取数得分之和。

帅帅想请你帮忙写一个程序,对于任意矩阵,可以求出取数后的最大得分。

Analysis

因为每行取数的策略可能不同,所以应该分行进行动规讨论。每行都要进行m次取数,每次取数的权值都是上一次的二倍。因为取数的分数是累计的,所以每次取完数后剩下部分也要求出最优策略,具备最优解子结构。那么

dp[i][j]=2*max(s[i]+dp[i+1][j],s[j]+dp[i][j-1])

到这里还没有结束,因为m<=80,所以最大是2^80,约合30位,所以高精度计算。

很坑的地方:因为状态转移中存在do[i+1][j],所以可能会数组越界,不能开到81。

Code

#include <bits/stdc++.h>

int n,m,s[1001];

struct bign{
	int len,num[101];
	bign operator = (bign eq){
		len=eq.len;
		memset(num,0,sizeof(num));
		for(int i=0;i<len;i++)
			num[i]=eq.num[i];
		return *this;
	}
	bign operator + (bign ad){
		bign ans;
		ans.len=std::max(len,ad.len);
		memset(ans.num,0,sizeof(ans.num));
		int accu=0;
		for(int i=0;i<ans.len;i++){
			int res=num[i]+ad.num[i]+accu;
			ans.num[i]=res%10;
			accu=res/10;
		}
		if(accu)ans.num[ans.len++]=accu;
		return ans;
	}
	bign operator + (int ad){
		bign eq;
		eq.len=0;
		memset(eq.num,0,sizeof(eq.num));
		while(ad){
			eq.num[eq.len++]=ad%10;
			ad/=10;
		}
		return *this+eq;
	}	
	bign operator += (bign ad){
		return *this=*this+ad;
	}
	bign operator += (int ad){
		return *this=*this+ad;
	}
	bool operator > (bign ad){
		if(len>ad.len)return 1;
		if(len<ad.len)return 0;
		for(int i=len-1;i>=0;i--)
			if(num[i]>ad.num[i])return 1;
			else if(num[i]<ad.num[i])return 0;
		return 0;
	} 
	friend std::ostream& operator << (std::ostream& out,bign ans){
		for(int i=ans.len-1;i+1;i--)
			out<<ans.num[i];
		return out;
	}
}ans,dp[81][81];

int main(){
	freopen("game.in","r",stdin);
	freopen("game.ans","w",stdout);
	std::cin>>n>>m;
	while(n--){
		for(int i=1;i<=m;i++)
			std::cin>>s[i];
		for(int l=1;l<=m;l++)
			for(int b=1;b<=m-l+1;b++){
				int e=b+l-1;
				bign la,ra;
				la=dp[b+1][e]+s[b];
				ra=dp[b][e-1]+s[e];
				dp[b][e]=la>ra?la+la:ra+ra;
			}
		ans+=dp[1][m];
	}
	std::cout<<ans<<std::endl;
	return 0;
}
posted @ 2018-08-17 11:41  Srzer  阅读(533)  评论(0编辑  收藏  举报