洛谷千题详解 | P1005 [NOIP2007 提高组] 矩阵取数游戏【C++、 Java、Python语言】

news2025/2/23 6:53:52

博主主页:Yu·仙笙

专栏地址:洛谷千题详解

目录

 题目描述

输入格式

输出格式

输入输出样例

解析: 

C++源码:

Java源码:

Python源码: 


------------------------------------------------------------------------------------------------------------------------------- 

-------------------------------------------------------------------------------------------------------------------------------  

 题目描述

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

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

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

-------------------------------------------------------------------------------------------------------------------------------  

输入格式

输入文件包括 n+1 行:

第一行为两个用空格隔开的整数 n 和 m。

第 2∼n+1 行为 n×m 矩阵,其中每行有 m 个用单个空格隔开的非负整数。

-------------------------------------------------------------------------------------------------------------------------------  

输出格式

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

-------------------------------------------------------------------------------------------------------------------------------  

输入输出样例

输入 #1

2 3
1 2 3
3 4 2

输出 #1

82

-------------------------------------------------------------------------------------------------------------------------------  

解析: 

求n行最大得分和,每一行取数又不会影响到其他行,那么只要确保每一行得分最大,管好自家孩子就行了。(这个在动规中叫最优子结构)

每次取数是在边缘取,那么每次取数完剩下来的元素一定是在一个完整的一个区间中,又是求最优解,区间DP应运而生。

-------------------------------------------------------------------------------------------------------------------------------  

C++源码:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>

using namespace std;

const int MAXN = 85, Mod = 10000; //高精四位压缩大法好 
int n, m;
int ar[MAXN];

struct HP {
	int p[505], len;
	HP() {
		memset(p, 0, sizeof p);
		len = 0;
	} //这是构造函数,用于直接创建一个高精度变量 
	void print() {
		printf("%d", p[len]);  
        for (int i = len - 1; i > 0; i--) {  
            if (p[i] == 0) {
				printf("0000"); 
				continue;
			}
            for (int k = 10; k * p[i] < Mod; k *= 10) 
				printf("0");
            printf("%d", p[i]);
        }
	} //四位压缩的输出 
} f[MAXN][MAXN], base[MAXN], ans;

HP operator + (const HP &a, const HP &b) {
	HP c; c.len = max(a.len, b.len); int x = 0;
	for (int i = 1; i <= c.len; i++) {
		c.p[i] = a.p[i] + b.p[i] + x;
		x = c.p[i] / Mod;
		c.p[i] %= Mod;
	}
	if (x > 0)
		c.p[++c.len] = x;
	return c;
} //高精+高精 

HP operator * (const HP &a, const int &b) {
	HP c; c.len = a.len; int x = 0;
	for (int i = 1; i <= c.len; i++) {
		c.p[i] = a.p[i] * b + x;
		x = c.p[i] / Mod;
		c.p[i] %= Mod;
	}
	while (x > 0)
		c.p[++c.len] = x % Mod, x /= Mod;
	return c;
} //高精*单精 

HP max(const HP &a, const HP &b) {
	if (a.len > b.len)
		return a;
	else if (a.len < b.len)
		return b;
	for (int i = a.len; i > 0; i--)
		if (a.p[i] > b.p[i])
			return a;
		else if (a.p[i] < b.p[i])
			return b;
	return a;
} //比较取最大值 

void BaseTwo() {
	base[0].p[1] = 1, base[0].len = 1;
	for (int i = 1; i <= m + 2; i++){ //这里是m! m! m! 我TM写成n调了n年... 
		base[i] = base[i - 1] * 2;
	}
} //预处理出2的幂 

int main(void) {
	scanf("%d%d", &n, &m);
	BaseTwo();
	while (n--) {
		memset(f, 0, sizeof f);
		for (int i = 1; i <= m; i++)
			scanf("%d", &ar[i]);
		for (int i = 1; i <= m; i++)
			for (int j = m; j >= i; j--) { //因为终值是小区间,DP自然就从大区间开始 
				f[i][j] = max(f[i][j], f[i - 1][j] + base[m - j + i - 1] * ar[i - 1]); 
				f[i][j] = max(f[i][j], f[i][j + 1] + base[m - j + i - 1] * ar[j + 1]);
			} //用结构体重载运算符写起来比较自然 
		HP Max;
		for (int i = 1; i <= m; i++)
			Max = max(Max, f[i][i] + base[m] * ar[i]);
		ans = ans + Max; //记录到总答案中 
	}
	ans.print(); //输出 
	return 0;
}

-------------------------------------------------------------------------------------------------------------------------------  

Java源码:

import java.math.BigInteger;
import java.util.Scanner;
 
public class Main {
	
	static int [] mp = new int[100];
	static BigInteger [] pow = new BigInteger[160];
	
    @SuppressWarnings("resource")
	public static void main(String[] args) {
    	pow[0] = BigInteger.ONE;
    	pow[1] = BigInteger.valueOf(2);
    	for(int i = 2; i < 160; i++) {
    		pow[i] = pow[1].pow(i);
    	}
    	Scanner cin = new Scanner(System.in);
    	BigInteger ans = BigInteger.ZERO;
    	int n=cin.nextInt(), m=cin.nextInt();
    	for(int t = 1; t <= n; t++) {
    		BigInteger [][] f = new BigInteger[100][100];
    		BigInteger max = BigInteger.ZERO;
    		for(int j = 1; j <= m; j++)
    			mp[j]=cin.nextInt();
    		for(int i = 0; i < 100; i++)
    			for(int j = 0; j < 100; j++)
    				f[i][j] = BigInteger.ZERO;
    		for(int i = 1; i <= m; i++)
    			for(int j = m; j > 0; j--) {
    				f[i][j] = f[i][j].max(f[i - 1][j].add(pow[m - j + i - 1].multiply(BigInteger.valueOf(mp[i - 1]))));
    				f[i][j] = f[i][j].max(f[i][j + 1].add(pow[m - j + i - 1].multiply(BigInteger.valueOf(mp[j + 1]))));
    			}
    		for(int i = 1; i <= m; i++)
    			max = max.max(f[i][i].add(pow[m].multiply(BigInteger.valueOf(mp[i]))));
    		ans = ans.add(max);
    	}
    	System.out.println(ans);
    }
}

-------------------------------------------------------------------------------------------------------------------------------  

Python源码: 

matrix=[]

n,m=input().split()
n,m=int(n),int(m)

for i in range(n):
    row=input().split()
    row=[0]+[int(count)for count in row]+[0]
    #print(row)
    # 把列表塞到列表里形成二维列表
    matrix.append(row)

a=[1]#a[0]=1初始化为1
#求到2^m
for i in range(m):
    a.append(a[i]*2)
    #print(a)
    
ans=0

for i in range(n):
    row=matrix[i]
    w=1
    #分配一个大小为m+2 * m+2的二维数组
    dp=[[0]*(m+2)]*(m+2)
    #print(dp)
    for st in range(1,m+1):
        for ed in range(m,0,-1):
            if ed<st:
                continue
            dp[st][ed]=max(dp[st-1][ed]+row[st-1]*a[m-ed+st-1],dp[st][ed+1]+row[ed+1]*a[m-ed+st-1])
            
    ans+=max([dp[i][i]+row[i]*a[m]for i in range(1,m+1)])
    
print(ans)

-------------------------------------------------------------------------------------------------------------------------------  

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2875.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

论文阅读之RETHINKING POSITIONAL ENCODING IN LANGUAGE PRE-TRAINING

文章目录论文阅读总结参考论文阅读 文章大概提出了两个问题&#xff1a; 1.对于原来的transformer或者bert的embedding中&#xff0c;直接将word embedding&#xff08;词向量&#xff09;和positional embedding &#xff08;位置编码&#xff09;相加是不合理的&#xff0c;…

Netty入门——组件(Channel)一

目录一、channel的主要作用二、EventLoop处理io任务代码示例2.1、服务端代码示例2.2、客户端代码示例2.3、服务端和客户端查看控制台输出结果三、ChannelFuture连接问题代码示例3.1、服务端代码示例3.2、客户端代码示例3.3、服务端和客户端查看控制台输出结果3.4、ChannelFutur…

MyBatis的二级缓存

MyBatis的二级缓存 二级缓存是SqlSessionFactory级别&#xff0c;通过同一个SqlSessionFactory创建的SqlSession查询的结果会被缓存&#xff1b;此后若再次执行相同的查询语句&#xff0c;结果就会从缓存中获取。 二级缓存开启的条件&#xff1a; 1.在核心配置文件中&#x…

软件测试:写一个好的测试用例

测试场景&#xff1a; 为登录功能设计测试用例 测试员为什么要会编测试用例 测试员的目标是要保证系统在各种场景下的功能是符合设计要求的。而测试用例就是测试员想到的测试场景。&#xff08;这也是高级别的测试员即使不会代码也能找到较好工作的原因&#xff09; 编写测试…

数据库2,DQL数据查询语言,表关联关系

目录 DQL数据查询语言 简单查询语句 计算列 别名 distinct消除重复行 条件查询 条件运算符 null值判断 枚举查询 模糊查询 分支查询 函数 字符串函数 聚合函数 排序查询 分组查询Group by 分页查询Limit 表关联关系 一对一关联 一对多与多对一 多对多关联 …

[CKA备考实验][ingress-nginx] 4.2 集群外访问POD

1.创建Deployments 部署方法请参照&#xff1a; https://blog.csdn.net/qq_33868661/article/details/127505429?spm1001.2014.3001.5501 apiVersion: apps/v1 kind: Deployment metadata:labels:name: deploy1annotations:name: deploy1name: deploy1namespace: default sp…

要么干要么滚!推特开始裁员了;深度学习产品应用·随书代码;可分离各种乐器音源的工具包;Transformer教程;前沿论文 | ShowMeAI资讯日报

&#x1f440;日报合辑 | &#x1f4c6;电子月刊 | &#x1f369;韩信子 &#x1f4e2; 解散Twitter董事会&#xff0c;代码审查&#xff0c;裁员25%&#xff0c;收每月20美元认证费马斯克那些骚操作 埃隆马斯克 (Elon Musk) 抱着洗手池入主 Twitter 后&#xff0c;狂风骤雨已…

STM32入门——uKeil5 MDK 的使用(基于固件库)

文章目录1 Keil uVision5 MDK 是什么2 建立一个标准库函数工程2.1 前期准备2.2 建立工程2.3 建立组文件夹2.4 添加文件2.4 配置“魔术棒”选项卡2.5 建立 main 函数1 Keil uVision5 MDK 是什么 Keil 软件是一种统称&#xff0c;它包含编辑器、编译器、链接器、调试器等众多工具…

冰冰学习笔记:二叉搜索树

欢迎各位大佬光临本文章&#xff01;&#xff01;&#xff01; 还请各位大佬提出宝贵的意见&#xff0c;如发现文章错误请联系冰冰&#xff0c;冰冰一定会虚心接受&#xff0c;及时改正。 本系列文章为冰冰学习编程的学习笔记&#xff0c;如果对您也有帮助&#xff0c;还请各位…

堆外内存和堆内内存及虚引用的应用

目录 内存区域划分&#xff1a; 元空间 程序计数器 直接内存 对象的创建 对象的访问定位 判断对象是否存活 堆外内存 堆内内存的缺点以及引入堆外内存 为什么需要堆外内存&#xff1f; 如何分配堆外内存&#xff1f; 如何回收堆外内存&#xff1f; 1) System.gc()…

C语言函数章--第二弹(让冤种室友用你的函数,但不给他看函数源码)

前言 &#x1f496;作者&#xff1a;龟龟不断向前 ✨简介&#xff1a;宁愿做一只不停跑的慢乌龟&#xff0c;也不想当一只三分钟热度的兔子。 &#x1f47b;专栏&#xff1a;C初阶知识点 &#x1f47b;工具分享&#xff1a; 刷题&#xff1a; 牛客网 leetcode笔记软件&#xff…

Error注入攻击

&#x1f4aa;&#x1f4aa;Error注入攻击1.创建漏洞环境2.漏洞攻击2.1判断是否有注入2.2信息收集2.3注入获取数据库名2.4注入获取表名2.5注入获取列名2.6注入获取信息3.sql靶场实战1.创建漏洞环境 &#x1f4aa;&#x1f4aa;第一步创建sql环境&#xff0c;直接再mysql下运行 …

Flutter——软件安装与环境配置

Flutter入门官网Flutter SDK下载创建Flutter项目在ios上运行第一个Flutter项目效果图代码总结官网 Flutter开发手册网址如下 Flutter SDK下载 下载地址 第一步&#xff1a;进入官网&#xff0c;选择自己相对应的系统 第二步&#xff1a;选择对应版本SDK并下载到本地 创建Flu…

electron调用dll文件

Electron 对系统层能力的使用可能比较弱&#xff0c;此时需要求助 Python、C、C# 等语言&#xff0c;通过 ffi-napi 库可以让 Node.js 使用 C dll&#xff0c;通过 electron-edge-js 库可以让 Node.js 使用 C# dll 1. 先确定dll文件是用什么语言写的. 使用peid 应用查看- 这个…

【Transformers】第 2 章:主题的实践介绍

&#x1f50e;大家好&#xff0c;我是Sonhhxg_柒&#xff0c;希望你看完之后&#xff0c;能对你有所帮助&#xff0c;不足请指正&#xff01;共同学习交流&#x1f50e; &#x1f4dd;个人主页&#xff0d;Sonhhxg_柒的博客_CSDN博客 &#x1f4c3; &#x1f381;欢迎各位→点赞…

Node.js | 基于 MongoDB 的简易用户管理系统

&#x1f5a5;️ NodeJS专栏&#xff1a;Node.js从入门到精通 &#x1f5a5;️ 博主的前端之路&#xff08;源创征文一等奖作品&#xff09;&#xff1a;前端之行&#xff0c;任重道远&#xff08;来自大三学长的万字自述&#xff09; &#x1f5a5;️ TypeScript知识总结&…

C++秋招经验贴

文章目录一、个人背景及秋招情况1.个人背景2.秋招情况二、求职C强相关开发岗位的准备过程以及一些建议1. 八股2. 力扣刷题3. 实习4. 项目三、总结一、个人背景及秋招情况 1.个人背景 本科&#xff1a;二本&#xff0c;材料专业   硕士&#xff1a;211硕&#xff0c;光学工程…

TI IWR1642毫米波雷达使用串口原始数据采集与分析

本文编辑&#xff1a;调皮哥的小助理 1.引言 如果文章能够给你带来价值&#xff0c;希望能够关注我。 如果文章能够让你学习到知识&#xff0c;希望你能够点个赞&#xff01; 好了下面开始今天的学习内容吧。 今天给大家分享的是 《TI 的IWR1642毫米波雷达使用串口原始数据…

深度学习入门(十五)环境和分布偏移(了解)

深度学习入门&#xff08;十五&#xff09;环境和分布偏移前言环境和分布偏移教材1 分布偏移的类型1.1 协变量偏移1.2 标签偏移1.3 概念偏移2 分布偏移示例2.1医学诊断2.2 自动驾驶汽车2.3 非平稳分布2.4 更多轶事3 分布偏移纠正3.1 经验风险与实际风险3.2 协变量偏移纠正3.3 标…

MATLAB | 一起来感受数学之美叭

前两天去观摩了MATHWORKS官方举办的Mathematics is beautiful数学之美投票比赛&#xff0c;见到了很多非常惊艳的作品&#xff0c;在这里分享给大家让大家一同感受大神们的创造力&#xff0c;接下来由我来做全程解说。 虽然看起来代码都写好了&#xff0c;&#xff0c;&#x…