题目描述

帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的\(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. 斐波那契数列&&上台阶

    使用装饰器的场景 当我们想对多个函数增加一个相同的功能时,例如计数统计,缓存计算结果,记录日志等 # coding:utf-8 # [题目1] # 斐波那契数列 又称黄金分割数列,指的是这样的一个数列 ...

  2. 【计算机视觉】基于OpenCV的人脸识别

    一点背景知识 OpenCV 是一个开源的计算机视觉和机器学习库.它包含成千上万优化过的算法,为各种计算机视觉应用提供了一个通用工具包.根据这个项目的关于页面,OpenCV 已被广泛运用在各种项目上,从 ...

  3. 高级UI-MD动画

    MD动画是谷歌推出的一种动画效果,其实现的效果能让用户看着很是舒服,符合MD动画的动画,有很强的用户交互体验 Touch Feedback(触摸反馈) 在触摸反馈这一块,用的最多的就是水波纹效果,而水 ...

  4. Linux下安装redis以及常用命令

    https://blog.csdn.net/zgf19930504/article/details/51850594 安装: 1.获取redis资源 wget http://download.redi ...

  5. rtsp向rtmp推流

    package com.awifi.video.media.test; import org.bytedeco.javacpp.avcodec; import org.bytedeco.javacv. ...

  6. GSVA的使用

    GSVA的简介 Gene Set Variation Analysis,被称为基因集变异分析,是一种非参数的无监督分析方法,主要用来评估芯片核转录组的基因集富集结果.主要是通过将基因在不同样品间的表达 ...

  7. 软件素材---C/C++格式化显示当前时间--标准函数strftime

    函数原型:size_t strftime (char* ptr, size_t maxsize, const char* format,const struct tm* timeptr ); 头文件: ...

  8. [WCF] - 使用 bat 批处理文件将 WCF 服务部署为 Windows Service

    1. 添加 Windows Service 项目 2. 添加 WCF 项目引用 3. 更新 App.config 配置文件(可以从 WCF的 Web.config 拷贝过来),设置服务地址. 4. 配 ...

  9. hdu 2167 题解

    题目 题意 一个数字正方形(所有数都是两位的正整数),取了一个数后,它的周围 $ 8 $ 个数都不能被选,问最大取数总和. 注意数据范围 $ 3=< n <=15 $ 我们可能一开始会去想 ...

  10. 使用keepalived实现kubenetes apiserver高可用

    # 安装 nginx yum install nginx -y # 配置nginx4层代理 /etc/nginx/nginx.conf stream { upstream kube-apiserver ...