题面

传送门:https://www.luogu.org/problemnew/show/P1005

Solution

我们可以先考虑贪心

我们每一次都选左右两边尽可能小的数,方便大的放在后面

听起来挺OK的

实则并不OK

反例:

3 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2

如果贪心的话,我们会优先把右边那一串2先选了,再去选3和1

但是正确答案显然是先把3和1选了,再去选那一串2


既然贪心不成,我们可以考虑一下DP

然后我们考虑这样一个状态:

f[i][j][k] 表示第i时刻,第j行,左边选到了第k列

因为我们知道了当前时刻和左边选到的列数,右边选到的列数也可以推算出来: m-i+k-1

然后就可以写出来一个比较显然的转移方程:

f[i][j][k]=max(f[i-1][j][k-1]+2^i*num[j][k-1],f[i-1][j][k]+2^i*num[j][m-i+k]) 

也就是第i时刻是选最左边的还是选右边的


这样子我们就可以得到 100分 60分

为什么会变成这样的呢?

原因很简单,我们仔细看一下数据范围:80

也就是说数据大小至少会有2^80

显然longlong (Int64)是放不下的

这时候,我们就需要伟大的Int128

你当然可以用stl的int128(虽然考试中不能用)

我们这里选用手写一个高精度类

我们只需要高精乘低精,高精加高精,高精比较大小

再加上若干时间的调试高精

然后就OjbK了

Code

//Luogu P1005 矩阵取数游戏
//DP+高精
//Apr,27th,2018
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
struct Int128
{
int a[50],len;
Int128()
{
memset(a,0,sizeof a);
len=0;
}
void Insert()
{
char c=getchar();
while(!isdigit(c)) c=getchar();
while(isdigit(c)){a[++len]=c-'0';c=getchar();}
int tot=len/2;
for(int i=len;i>tot;i--)swap(a[i],a[len-i+1]);
}
void Print()
{
for(int i=len;i>=1;i--)
printf("%d",a[i]);
}
friend Int128 operator * (Int128 a,int b)
{
Int128 ans=Int128();
ans.len=a.len;
for(int i=1;i<=ans.len;i++)
{
ans.a[i]+=a.a[i]*b;
ans.a[i+1]+=ans.a[i]/10;
ans.a[i]%=10;
if(i==ans.len and ans.a[i+1]!=0)
ans.len++;
}
return ans;
}
friend Int128 operator + (Int128 a,Int128 b)
{
Int128 ans=Int128();
ans.len=max(a.len,b.len);
for(int i=1;i<=ans.len;i++)
{
ans.a[i]+=a.a[i]+b.a[i];
ans.a[i+1]+=ans.a[i]/10;
ans.a[i]%=10;
if(i==ans.len and ans.a[i+1]!=0)
ans.len++;
}
return ans;
}
friend bool operator < (Int128 a,Int128 b)
{
if(a.len<b.len) return true;
if(a.len>b.len) return false;
for(int i=a.len;i>=1;i--)
if(a.a[i]>b.a[i])
return false;
else if(a.a[i]<b.a[i])
return true;
return false;
}
};
const int N=80+10;
Int128 f[2][N][N],POW[N];
int a[N][N];
int n,m;
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
scanf("%d",&a[i][j]); POW[1].len=1,POW[1].a[1]=2;
for(int i=2;i<=m;i++)
POW[i]=POW[i-1]*2;
for(int i=1;i<=m;i++)
for(int j=1;j<=n;j++)
for(int k=1;k<=i+1;k++)
{
if(k>1)
f[i%2][j][k]=f[(i-1)%2][j][k-1]+POW[i]*a[j][k-1];
if(m-i+k-1<m)
f[i%2][j][k]=max(f[i%2][j][k],f[(i-1)%2][j][k]+POW[i]*a[j][m-i+k]);
//f[i%2][j][k].Print();
//cout<<endl;
} Int128 ans=Int128();
for(int i=1;i<=n;i++)
{
Int128 t_ans=Int128();
for(int j=1;j<=m;j++)
t_ans=max(t_ans,f[m%2][i][j]);
ans=ans+t_ans;
} ans.Print();
return 0;
}

[LuoguP1005]矩阵取数游戏 (DP+高精度)的更多相关文章

  1. [luoguP1005] 矩阵取数游戏(DP + 高精度)

    传送门 和奶牛那个题很像,每一行状态互不影响,也就是求 n 遍DP 不过高精度非常恶心,第一次写,调了我一上午. ——代码 #include <cstdio> #include <c ...

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

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

  3. [P1005][NOIP2007] 矩阵取数游戏 (DP+高精)

    我不会高精…… 也不会DP…… 这道题即考高精又考DP…… 我要死了 给一个不是高精的代码(当然不能满分) #include<cstdio> #include<iostream> ...

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

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

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

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

  6. P1005 矩阵取数游戏[区间dp]

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

  7. 矩阵取数游戏 2007年NOIP全国联赛提高组(dp+高精)

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

  8. 矩阵取数游戏 NOIP 2007

    2016-05-31 17:26:45 题目链接: NOIP 2007 矩阵取数游戏(Codevs) 题目大意: 给定一个矩阵,每次在每一行的行首或者行尾取一个数乘上2^次数,求取完最多获得的分数 解 ...

  9. 矩阵取数游戏洛谷p1005

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

随机推荐

  1. Tomcat 8.5集群配置

    示例 <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster" channelSendOptions= ...

  2. Python练习题 011:成绩打分

    [Python练习题 011] 利用条件运算符的嵌套来完成此题:学习成绩>=90分的同学用A表示,60-89分之间的用B表示,60分以下的用C表示. ---------------------- ...

  3. GOOGLE工作法(世界一速)|木深读书笔记

  4. Java知识系统回顾整理01基础03变量09块

    一.定义 块:从{ 开始 到对应的} 结束,即一个块 public class HelloWorld { //类对应的块 public static void main(String[] args) ...

  5. Python3基础——序列类型

    开头写给自己,To Myself: 很久以来,都想要学习一门编程语言,从去年选择了python开始,反反复复重新开始了N多遍,每一次不会超过俩星期.昨天无意间翻开自己去年记的学习笔记,不禁感叹想当年我 ...

  6. 【题解】「MCOI-02」Convex Hull 凸包

    题目戳我 \(\text{Solution:}\) \[\sum_{i=1}^n \sum_{j=1}^n \rho(i)\rho(j)\rho(\gcd(i,j)) \] \[=\sum_{d=1} ...

  7. python实现单链表及链表常用功能

    单链表及增删实现 单链表高级功能实现:反序,找中间结点,检测环等 参考: https://github.com/wangzheng0822/algo

  8. Python+Appium自动化测试(15)-使用Android模拟器(详细)

    做APP的UI自动化测试时,我们往往会使用真机跑自动化测试脚本,因为这样才是最真实的使用场景.但前期调试脚本的话,可以先使用模拟器,这样相对更加方便. 不推荐使用Android SDK里自带模拟器,太 ...

  9. 游戏2048的核心算法c#版本的实现

    接触游戏有一段时间了,也写了一些东西,效果还不错,今天没事,我就把2048 c# 版本的实现贴出来,代码已经测试过,可以正常.完美运行.当然了,在网上有很多有关2048的实现方法,但是没有提出到类里面 ...

  10. TiOps,支持容器,支持多云安全远程运维,疫情期间免费开放,助力远程办公

    TiOps,支持多云环境安全远程运维,疫情期间免费对外开放在疫情期间,为减少疾病传染可能性,许多公司的选择了在家远程办公.对于运维来说,既要远程运维,又要保证安全,还要在复杂的IT环境中保持高效,面临 ...