1166 矩阵取数游戏[区间dp+高精度]
【问题描述】
帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的n*m 的矩阵,矩阵中的每个元素aij均
为非负整数。游戏规则如下:
1. 每次取数时须从每行各取走一个元素,共n个。m次后取完矩阵所有元素;
2. 每次取走的各个元素只能是该元素所在行的行首或行尾;
3. 每次取数都有一个得分值,为每行取数的得分之和,每行取数的得分= 被取走的元素值*2i,
其中i 表示第i 次取数(从1 开始编号);
4. 游戏结束总得分为m次取数得分之和。
帅帅想请你帮忙写一个程序,对于任意矩阵,可以求出取数后的最大得分。
第1行为两个用空格隔开的整数n和m。
第2~n+1 行为n*m矩阵,其中每行有m个用单个空格隔开的非负整数。
输出 仅包含1 行,为一个整数,即输入矩阵取数后的最大得分。
2 3
1 2 3
3 4 2
82
样例解释
第 1 次:第1 行取行首元素,第2 行取行尾元素,本次得分为1*21+2*21=6
第2 次:两行均取行首元素,本次得分为2*22+3*22=20
第3 次:得分为3*23+4*23=56。总得分为6+20+56=82
【限制】
60%的数据满足:1<=n, m<=30, 答案不超过1016
100%的数据满足:1<=n, m<=80, 0<=aij<=1000
题解:个人觉得拿到60分就好,AC需要用高精度处理(特别恶心)。
60分代码(long long即可)
//2016/04/02 16:36:32
#include<bits/stdc++.h>
#define ref(i,x,y) for(long long i=x;i<=y;i++)
using namespace std;
long long f[][];
long long a[][];
long long xm[];
long long n,m,sum,ans;
int main(){
scanf("%d%d",&n,&m);xm[]=;
ref(i,,) xm[i]=xm[i-]<<;//2的i次幂
ref(i,,n)ref(j,,m)
scanf("%d",&a[i][j]);
ref(j,,n){
memset(f,,sizeof(f));//清零
ans=;
ref(i,,m) ref(x1,,i){//f[i][j]=max(f[i-1][j(当前列标-i)]+a[k(第几个)][i]*2^i,f[i][j-1]+a[k][m+1-j]*2^i)
long long x2=i-x1;
f[x1][x2]=max(f[x1-][x2]+a[j][x1]*xm[i],f[x1][x2-]+a[j][m-x2+]*xm[i]);
ans=max(f[x1][x2],ans);
}
sum+=ans;
}
cout<<sum<<endl;
return ;
}
AC代码:
1。INF进制版高精度+dp
#include <cstdio>
#define ref(i,x,y) for(int i=x;i<=y;i++)
#define INF 10000000000000000ll//考虑到long long 后边有011,19位数必须是素数
#define N 81
using namespace std;
struct node{//INF进制的高精度
long long num[];//19位压一组,压2组就好--最多27,、28位
}s,f[N][N],w,r;//w r 左右边
int a[N][N],n,m;
int main(){
scanf("%d%d",&n,&m);
ref(i,,n)
ref(j,,m)
scanf("%d",&a[i][j]),a[i][j]<<=;//先乘2 之后可以直接高精
s.num[]=0ll;//考虑与INF尾部匹配
s.num[]=0ll;
ref(l,,n){
ref(j,,m)
ref(k,,m){
f[j][k].num[]=0ll;
f[j][k].num[]=0ll;
}
ref(i,,m)
f[i][i].num[]=a[l][i];
ref(i,,m)
ref(j,,m-i+){
int k=j+i-;
w.num[]=0ll;
w.num[]=0ll;
r.num[]=0ll;
r.num[]=0ll;
w.num[]=f[j][k-].num[]*;
w.num[]=f[j][k-].num[]*;
if(w.num[]>=INF)
w.num[]%=INF,w.num[]++;
w.num[]+=a[l][k];
if(w.num[]>=INF)
w.num[]%=INF,w.num[]++;
r.num[]=f[j+][k].num[]<<1ll;
r.num[]=f[j+][k].num[]<<1ll;
if(r.num[]>=INF)
r.num[]%=INF,r.num[]++;
r.num[]+=a[l][j];
if(r.num[]>=INF)
r.num[]%=INF,r.num[]++;
f[j][k]=(w.num[]>r.num[]||w.num[]==r.num[]&&w.num[]>r.num[])?w:r;
}
s.num[]+=f[][m].num[];
s.num[]+=f[][m].num[];
if(s.num[]>=INF)
s.num[]%=INF,s.num[]++;
}
if(s.num[])//是否高于19位
printf("%lld%lld\n",s.num[],s.num[]);
else
printf("%lld\n",s.num[]);
return ;
}
2。 10进制版高精度 +dp
#include<bits/stdc++.h>
using namespace std;
#define N 90
int n,m;bool b;
int a[N],f[N][N][N];
int le[N],ri[N],s[N];//高精度处理数组
int main(){
scanf("%d%d",&n,&m);
for(int k=;k<=n;k++){
memset(a,,sizeof a);
memset(f,,sizeof f);
for(int i=;i<=m;i++) scanf("%d",&a[i]);
for(int i=;i<=m;i++) //i表示长度
for(int j=;j+i-<=m;j++){//j表示左端点
//f[j][j+i-1]=max(f[j][j+i-2]*2+a[j+i-1],f[j+1][j+i-1]*2+a[j]);
memset(le,,sizeof le);
memset(ri,,sizeof ri);
for(int t=;t<N;t++) le[t]=f[j][j+i-][t]*;
le[]+=a[j+i-];
for(int t=;t<N-;t++)//10进制高精度跑的有点慢
le[t+]+=le[t]/,le[t]%=;
for(int t=;t<N;t++) ri[t]=f[j+][j+i-][t]*;
ri[]+=a[j];
for(int t=;t<N-;t++)
ri[t+]+=ri[t]/,ri[t]%=;
int t1=N-,t2=N-;
while(le[t1]==&&t1!=) t1--;
while(ri[t2]==&&t2!=) t2--;
if(t1>t2) b=;
else if(t1<t2) b=;
else
for(int q=t2;q>=;q--)
if(le[q]>ri[q]){
b=;break;
}
else if(le[q]<ri[q]){
b=; break;
}
if(b)
for(int q=t1;q>=;q--) f[j][j+i-][q]=le[q];
else
for(int q=t2;q>=;q--) f[j][j+i-][q]=ri[q];
}
for(int i=;i<N;i++) s[i]+=f[][m][i];
}
for(int i=;i<N;i++) s[i]*=;
for(int i=;i<N-;i++){
s[i+]+=s[i]/;
s[i]%=;
}
int w=N-;
while(s[w]==&&w) w--;
for(int j=w;j>=;j--) printf("%d",s[j]);
return ;
}
对比:
1166 矩阵取数游戏[区间dp+高精度]的更多相关文章
- P1005 矩阵取数游戏 区间dp 高精度
题目描述 帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的n \times mn×m的矩阵,矩阵中的每个元素a_{i,j}ai,j均为非负整数.游戏规则如下: 每次取数时须从每行各取走一个元素,共n ...
- P1005 矩阵取数游戏[区间dp]
题目描述 帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的\(m*n\)的矩阵,矩阵中的每个元素\(a_{i,j}\)均为非负整数.游戏规则如下: 每次取数时须从每行各取走一个元素,共n个.经过m次后 ...
- [luoguP1005] 矩阵取数游戏(DP + 高精度)
传送门 和奶牛那个题很像,每一行状态互不影响,也就是求 n 遍DP 不过高精度非常恶心,第一次写,调了我一上午. ——代码 #include <cstdio> #include <c ...
- codevs 1166 矩阵取数游戏
二次联通门 : codevs 1166 矩阵取数游戏 /* codevs 1166 矩阵取数游戏 SB区间dp dp[l][r] = max (dp[l + 1][r] + number[l], dp ...
- Codevs_1166_[NOIP2007]_矩阵取数游戏_(动态规划+高精度)
描述 http://codevs.cn/problem/1166/ 分析 #include <iostream> #include <cstring> #include < ...
- wikioi 1166 矩阵取数游戏
这题做了至少5个小时= =,虽然思路一开始就确定了,但是因为一些错误,比如dp公式里的+打成*,状态未初始化等原因调了好久(>_<) 最后还是参照着别人的解题报告找到错误. 大数模板直接拿 ...
- P1005 矩阵取数游戏(动态规划+高精度)
题目链接:传送门 题目大意: 给定长度为m的数列aj,每次从两端取一个数,得到2k * aj的价值(k为当前的次数,从1开始到m),总共有n行这样的数列,求最大价值总和. 1 ≤ n, m ≤ 80, ...
- 矩阵取数游戏 NOIP 2007
2016-05-31 17:26:45 题目链接: NOIP 2007 矩阵取数游戏(Codevs) 题目大意: 给定一个矩阵,每次在每一行的行首或者行尾取一个数乘上2^次数,求取完最多获得的分数 解 ...
- [LuoguP1005]矩阵取数游戏 (DP+高精度)
题面 传送门:https://www.luogu.org/problemnew/show/P1005 Solution 我们可以先考虑贪心 我们每一次都选左右两边尽可能小的数,方便大的放在后面 听起来 ...
随机推荐
- 对于C语言中数组名是指针的理解
我们都知道,c语言中数组名是一个指针,比如下面这段代码 #include<iostream>using namespace std;int main(){ int a[4]={1,2,3, ...
- nutch-2.2.1 hadoop-1.2.1 hbase-0.92.1 集群部署
国内私募机构九鼎控股打造APP,来就送 20元现金领取地址:http://jdb.jiudingcapital.com/phone.html 内部邀请码:C8E245J (不写邀请码,没有现金送) 国 ...
- 解决黑苹果与windows时区不一致
原理就是将windows识别硬件时间为UTC-0而不是现在的UTC+8 下面都是抄来的 注册表HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\T ...
- Codeforces Beta Round #29 (Div. 2, Codeforces format) C. Mail Stamps 离散化拓扑排序
C. Mail Stamps Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/problemset/problem ...
- MySQL CAST与CONVERT 函数的用法
MySQL CAST与CONVERT 函数的用法 产生另一个类型的值 MySQL 的CAST()和CONVERT()函数可用来获取一个类型的值,并产生另一个类型的值. 两者具体的语法如下:1 CAS ...
- [AngularJS] TweenList 3D + AngularJS Animate
AngularJS animations and TweenLite make it really easy to create cool 3d effects in your application ...
- 读取svg图片为UIBezierPath,开心做动画
动画预览 先扯淡 最近手痒又想整点动画玩玩,但是想了几个主意发现稍微复杂一点的手写都一定会累爆.这篇文章记录一下今天折腾的一个方案.说来简单,就是用矢量设计工具舒舒服服的做好设计,然后输出成 svg ...
- jQuery 的 live() 方法对 hover 事件的处理
因为hover不是标准的事件,因此无法直接使用live进行处理,故使用以下方法代替,效果一样 <script type="text/javascript"> $(&qu ...
- SQL SERVER-Delete和Truncate的区别
背景: 一般在删除表数据时候,通常会有执行两个SQL语句:delete和truncate,有条件的删除我们平时都会用delete,而如果全部删除,那我们通常都会选择truncate,因为这 ...
- 虚拟机Linux和Windows之间互传文件的好帮手WinSCP
WinSCP下载地址:http://download.pchome.net/internet/ftp/down-34064-1.html 安装很简单,这里就不做介绍.下面是启动后的界面: 在主机名(H ...