题目描述

帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的\(m*n\)的矩阵,矩阵中的每个元素\(a_{i,j}\)均为非负整数。游戏规则如下:

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

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

解析

除了脑残高精度(反正窝用__int128硬生生水了过去,但是考场上不能用啊),是道还行的dp题。

窝的做法比起其它题解的做法low了很多,时间和空间效率都不是十分优秀,而且也似乎有人用了,还比我快(哭。


观察题目,容易发现我们只能对每行分开进行\(dp\),而对每行的\(dp\)实际上就是一个区间\(dp\),从大区间缩小到小区间。

设\(dp[i][l][r][j]\)表示第\(i\)次取数时,第\(j\)行左边界取到\(l\),右边界取到\(r\)时的最优解。

得到状态转移方程:

\[dp[i][l][r][j]=\max\limits_{i \in [1,m],j \in [1,n]} \{dp[i-1][l-1][r][j]+num[j][l-1]*2^i,dp[i-1][l][r+1][j]+num[j][r+1]*2^i\}
\]

如果直接这么写会炸空间。

观察状态转移方程发现一个状态只与它上一个状态有关,于是考虑一个滚动数组优化。

参考代码

#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#include<ctime>
#include<cstdlib>
#include<algorithm>
#include<queue>
#include<set>
#include<map>
#define N 101
#define ll __int128
#define INF 0x7ffffffff
using namespace std;
ll dp[2][N][N][N],n,m,a[N][N];//dp[i][l][r][j]表示第i次取数第j行的最大得分,左端点l,右端点r
inline ll read()
{
int f=1,x=0;char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
return x*f;
}
inline ll qp(ll a,ll b)//快速幂
{
ll ans=1;
for(;b;b>>=1){if(b&1)ans*=a;a*=a;}
return ans;
}
void print(ll x)//暴躁老哥,在线__int128
{
if(!x) return;
if(x) print(x/10);
putchar(x%10+'0');
}
int main()
{
n=read(),m=read();
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j) a[i][j]=read();
memset(dp,~0x3f,sizeof(dp));
int now=0;
for(int i=1;i<=n;++i) dp[0][1][m][i]=0;//初始化,不细讲
for(int k=1;k<=m;++k){
now^=1;
for(int i=1;i<=n;++i){
for(int l=1;l<=k+1;++l){
ll r=l+m-k-1;
dp[now][l][r][i]=max(dp[now][l][r][i],max(dp[now^1][l-1][r][i]+a[i][l-1]*qp(2,k),dp[now^1][l][r+1][i]+a[i][r+1]*qp(2,k)));
}
}
}
ll ans=0;
for(int i=1;i<=n;++i){
ll maxx=-INF;
for(int l=1;l<=m;++l)、
//寻找每一行的最优解
maxx=max(maxx,max(dp[now][l][l+1][i],dp[now][l+1][l][i]));
//最后一步会出现两种状态,都要统计
ans+=maxx;
}
if(!ans) printf("0\n");
else print(ans);
return 0;
}

P1005 矩阵取数游戏[区间dp]的更多相关文章

  1. P1005 矩阵取数游戏 区间dp 高精度

    题目描述 帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的n \times mn×m的矩阵,矩阵中的每个元素a_{i,j}ai,j​均为非负整数.游戏规则如下: 每次取数时须从每行各取走一个元素,共n ...

  2. 1166 矩阵取数游戏[区间dp+高精度]

    1166 矩阵取数游戏 2007年NOIP全国联赛提高组  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 黄金 Gold 题解       题目描述 Description [ ...

  3. 洛谷P1005 矩阵取数游戏

    P1005 矩阵取数游戏 题目描述 帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的n*m的矩阵,矩阵中的每个元素aij均为非负整数.游戏规则如下: 1.每次取数时须从每行各取走一个元素,共n个.m次 ...

  4. [NOIP2007] 提高组 洛谷P1005 矩阵取数游戏

    题目描述 帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的n*m的矩阵,矩阵中的每个元素aij均为非负整数.游戏规则如下: 1.每次取数时须从每行各取走一个元素,共n个.m次后取完矩阵所有元素: 2. ...

  5. 洛谷 P1005 矩阵取数游戏

    题目描述 帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的n*m的矩阵,矩阵中的每个元素aij均为非负整数.游戏规则如下: 1.每次取数时须从每行各取走一个元素,共n个.m次后取完矩阵所有元素: 2. ...

  6. 洛谷 P1005 矩阵取数游戏 (区间dp+高精度)

    这道题大部分时间都在弄高精度-- 还是先讲讲dp吧 这道题是一个区间dp,不过我还是第一次遇到这种类型的区间dp f[i][j]表示取了数之后剩下i到j这个区间的最优值 注意这里是取了i之前和j之后的 ...

  7. 【Luogu】P1005矩阵取数游戏(高精度+DP)

    题目链接 yeah终于过辣! DP,f[i][j]表示每行还剩i到j这个区间的数没取的时候的值.借这个题我也把高精度的短板弥补了一下,以后高精加高精乘应该是没问题了. 哇终于不怂高精了…… 放上代码. ...

  8. P1005 矩阵取数游戏

    传送门 思路: △ 区间动规 对于每行,有 f [ i ][ j ] 代表取区间 [ i , j ] 的最大值. 然后转移方程我们考虑,对于每一个新的 f [ i ][ j ],有两种情况(下面定义  ...

  9. P1005 矩阵取数游戏(动态规划+高精度)

    题目链接:传送门 题目大意: 给定长度为m的数列aj,每次从两端取一个数,得到2k * aj的价值(k为当前的次数,从1开始到m),总共有n行这样的数列,求最大价值总和. 1 ≤ n, m ≤ 80, ...

随机推荐

  1. Docker 安装运行MySQL

    1.镜像主页 https://hub.docker.com/_/mysql 2.拉取5.7版本 docker pull mysql:5.7 3.或者拉取最新8.x版本 docker pull mysq ...

  2. top命令常用

    top 使用时的命令: Ctrl+L擦除并且重写屏幕. h或者?显示帮助画面,给出一些简短的命令总结说明. k 终止一个进程.系统将提示用户输入需要终止的进程PID,以及需要发送给该进程什么样的信号. ...

  3. linux 下安装docker

    Linux 下的 Docker 安装与使用 一.安装与配置 安装一些必要的系统工具: sudo yum install -y yum-utils device-mapper-persistent-da ...

  4. Asp.Net Core中完成拒绝访问功能

    很多时候如果用户没有某个菜单的操作权限的话在页面是不应该显示出来的. @if (SignInManager.IsSignedIn(User) && User.IsInRole(&quo ...

  5. SQL 先固定特殊的几行数据之外再按照某一字段排序方法(CASE 字段排序(CASE WHEN THEN)

    查询用户表的数据,管理员用户始终在最前面,然后再按照CreateTime排序: SELECT TOP * FROM [dbo].[User] WHERE ParentID = '**' ORDER B ...

  6. poj 1852&3684 题解

    poj 1852 3684 这两题思路相似就放在一起. 1852 题意 一块长为L长度单位的板子(从0开始)上有很多只蚂蚁,给出它们的位置,它们的方向不确定,速度为每秒一长度单位,当两只蚂蚁相遇的时候 ...

  7. Python重要配置大全

    PYTHON 环境安装 安装虚拟环境 pip install virtualenv 卸载包是用:pip uninstall virtualenv 快捷下载安装可用豆瓣源,方法为: pip instal ...

  8. shell 学习笔记3-shell变量扩展

    一.特殊位置参数变量 1.特殊位置参数变量 在shell中比如:$0.$1.$#,等被称为特殊位置参数变量,当命令行.函数.脚本执行等处传递参数时,就需要使用位置参数变量 参数说明如下: 2.示例$1 ...

  9. Go 终端读写 && 文件读写、copy

    终端读写 操作终端相关文件句柄常量 os.Stdin(standard):标准输入 os.Stdout:标准输出 os.Stderr:标准错误输出 标准输出 demo:直接输出和 判断之后输出的结果不 ...

  10. robot framework 的关键字Continue For Loop 用法

    Continue For Loop关键字就是python的continue的意思,跳出本层循环,继续执行下一个循环. 我先举个栗子: :FOR    ${index}    IN RANGE    5 ...