题面

传送门: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. 使用内置对象Math.random实现猜数字游戏

    function getRandom(min,max){ return Math.floor(Math.random()*(max-min+1))+min;    //得到两个数之间的随机整数,包含实 ...

  2. ACMer不得不会的线段树,究竟是种怎样的数据结构?

    大家好,欢迎阅读周三算法数据结构专题,今天我们来聊聊一个新的数据结构,叫做线段树. 线段树这个数据结构很多人可能会有点蒙,觉得没有听说过,但是它非常非常有名,尤其是在竞赛圈,可以说是竞赛圈的必备技能. ...

  3. 计算(calc)

    计算(calc) [题目描述] 小明在你的帮助下,破密了Ferrari设的密码门,正要往前走,突然又出现了一个密码门,门上有一个算式,其中只有"(",")",& ...

  4. Java知识系统回顾整理01基础05控制流程03 while

    while和do-while循环语句 一.while:条件为true时 重复执行 只要while中的表达式成立,就会不断地循环执行 public class HelloWorld { public s ...

  5. 插头 dp

    插头dp 洛谷 黑题板子? P5056 给出n×m的方格,有些格子不能铺线,其它格子必须铺,形成一个闭合回路.问有多少种铺法? 1.轮廓线 简单地说,轮廓线就是已决策格子和未决策格子的分界线: 2,插 ...

  6. Jmeter之『JSR223脚本』

    Json处理(通过JS) 对于Json字符串,需要使用单引号『''』(因为Json中已存在双引号) // String转为Object var jsonObj = JSON.parse('${data ...

  7. 状压DP——【蜀传之单刀赴会】

    某王   老师今天考了一套三国题,AK了...就挑一道最恶心的题来写一写吧. 题目描述: [题目背景] 公元215年,刘备取益州,孙权令诸葛瑾找刘备索要荆州.刘备不答应,孙权极为恼恨,便派吕蒙率军取长 ...

  8. Go语言中的常见的几个坑

    目录 1.for range 2.defer与闭包 3.map内存溢出 4.协程泄漏 5.http手动关闭 记录一下日常中遇到的几个坑,加深一下印象. 1.for range 这个是比较常见的问题了, ...

  9. BUUCTF_web_三

    下面还是简单web的入门题 [GKCTF2020]cve版签到 这次的比赛最简单的题了吧,提示是CVE-2020-7066,但是网上没有几个关于这个漏洞的相关利用的文章,似乎是get_header() ...

  10. 解决:npm install ERR! Unexpected end of JSON input

    npm ERR! Unexpected end of JSON input npm i -g npm@5 npm install --registry=https://registry.npm.tao ...