[LuoguP1005]矩阵取数游戏 (DP+高精度)
题面
传送门: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+高精度)的更多相关文章
- [luoguP1005] 矩阵取数游戏(DP + 高精度)
传送门 和奶牛那个题很像,每一行状态互不影响,也就是求 n 遍DP 不过高精度非常恶心,第一次写,调了我一上午. ——代码 #include <cstdio> #include <c ...
- 【Luogu】P1005矩阵取数游戏(高精度+DP)
题目链接 yeah终于过辣! DP,f[i][j]表示每行还剩i到j这个区间的数没取的时候的值.借这个题我也把高精度的短板弥补了一下,以后高精加高精乘应该是没问题了. 哇终于不怂高精了…… 放上代码. ...
- [P1005][NOIP2007] 矩阵取数游戏 (DP+高精)
我不会高精…… 也不会DP…… 这道题即考高精又考DP…… 我要死了 给一个不是高精的代码(当然不能满分) #include<cstdio> #include<iostream> ...
- 1166 矩阵取数游戏[区间dp+高精度]
1166 矩阵取数游戏 2007年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题解 题目描述 Description [ ...
- P1005 矩阵取数游戏 区间dp 高精度
题目描述 帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的n \times mn×m的矩阵,矩阵中的每个元素a_{i,j}ai,j均为非负整数.游戏规则如下: 每次取数时须从每行各取走一个元素,共n ...
- P1005 矩阵取数游戏[区间dp]
题目描述 帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的\(m*n\)的矩阵,矩阵中的每个元素\(a_{i,j}\)均为非负整数.游戏规则如下: 每次取数时须从每行各取走一个元素,共n个.经过m次后 ...
- 矩阵取数游戏 2007年NOIP全国联赛提高组(dp+高精)
矩阵取数游戏 2007年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题目描述 Description [问题描述]帅帅经常跟 ...
- 矩阵取数游戏 NOIP 2007
2016-05-31 17:26:45 题目链接: NOIP 2007 矩阵取数游戏(Codevs) 题目大意: 给定一个矩阵,每次在每一行的行首或者行尾取一个数乘上2^次数,求取完最多获得的分数 解 ...
- 矩阵取数游戏洛谷p1005
题目描述 帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的n*m的矩阵,矩阵中的每个元素aij均为非负整数.游戏规则如下: 1.每次取数时须从每行各取走一个元素,共n个.m次后取完矩阵所有元素: 2. ...
随机推荐
- centos7修改ssh端口及添加ssh监听端口
ssh 修改默认端口 [root@node-1 ~]# vi /etc/ssh/sshd_config 修改port 为 5522 重启[root@node-1 ~]# systemctl resta ...
- Linux为STDOUT的关键字设置颜色
echo "颜色测试aaa实测" | perl -pe 's/(aaa|实|测)/\e[1;31m$1\e[0m/g'
- Ubuntu18.04修改apt-get源
1)备份源文件: sudo cp /etc/apt/sources.list /etc/apt/sources.list.bak 2)查看版本信息 如是Linux Mint等Ubuntu衍生版,执行: ...
- SHOI 2013 【扇形面积并】
早上考的,我打了80分的部分分,出来和同学讨论的时候真想扇自己一巴掌...... 题目描述: 给定 n 个同心的扇形,求有多少面积,被至少k 个扇形所覆盖. 输入输出格式 输入格式: 第一行是三个整数 ...
- 《New Horizon College English》 (Third Edition) -长篇阅读(Skmming and Scanning)
<New Horizon College English>(Third Edition) <新视野大学英语>(第三版) 长篇阅读(Skmming and Scanning) 总 ...
- TP5自定义路由,为了安全性
1,入口文件index.php,不要指定任意模块,不然,自定义路由,就不会有任何效果哦 2,在配置文件 route.php 中引进 use think\Router 自带路由文件 3,将路由进 ...
- redis哨兵搭建
redis哨兵搭建 1.复制配置文件到conf #单机安装以后[root@t3 redis-5.0.8]# pwd/app/redis-5.0.8[root@t3 redis-5.0.8]# cp s ...
- 利用babel工具将es6语法转换成es5,Object.assign方法报错
一.新建工程初始化项目 1.新建工程文件夹这里起名叫做es6,然后在里面创建两个文件夹分别为src .dist如下图:(src为待转换es6 js存放目录,dist为编译完成后的es5 js存放目录) ...
- java中文件是否为空
在File类中并没有提供判断文件是否为空的方法,但可以借助length()方法的返回值进行判断.如果文件不存在或文件为空时,length()方法返回0. File file = new File(&q ...
- 【并查集】BZOJ 1854 连续攻击游戏
题目内容 洛谷链接 lxhgww最近迷上了一款游戏,在游戏里,他拥有很多的装备,每种装备都有2个属性,这些属性的值用[1,10000]之间的数表示.当他使用某种装备时,他只能使用该装备的某一个属性.并 ...