zoukankan      html  css  js  c++  java
  • 矩阵取数

    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;
    }
    
  • 相关阅读:
    rt_thread studio结合cubmx进行stm32驱动开发学习
    rt_thread之时钟管理
    rt_thread线程间通讯
    使用jQuery开发iOS风格的页面导航菜单
    使用jQuery开发一个带有密码强度检验的超酷注册页面
    使用Javascript来创建一个响应式的超酷360度全景图片查看幻灯效果
    [英] 推荐 15 个 jQuery 选择框插件
    JavaScript封装Ajax(类JQuery中$.ajax()方法)
    阿里前端电话面试
    基于HTML5的Web跨设备超声波通信方案
  • 原文地址:https://www.cnblogs.com/qswx/p/9492520.html
Copyright © 2011-2022 走看看