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 我们可以先考虑贪心 我们每一次都选左右两边尽可能小的数,方便大的放在后面 听起来 ...
随机推荐
- [转]Kerberos简介
Kerberos协议: Kerberos协议主要用于计算机网络的身份鉴别(Authentication), 其特点是用户只需输入一次身份验证信息就可以凭借此验证获得的票据(ticket-grantin ...
- Junit 测试断言说明
Assert.assertEquals("发生错误时报告消息","预期值","生产值"); Assert.assertEquals(&quo ...
- Tun/Tap interface tutorial
Foreword: please note that the code available here is only for demonstration purposes. If you want t ...
- sql server2008评估期已过...问题
sql server2008评估期已过...问题 当打开sql server2008企业管理器的时候,出现报错“评估期已过.有关如何升级的测试版软件的信息.....” 工具/原料 sql serv ...
- 全代码实现ios-2
全代码开发ios第一个应用程序,完全像是盲人摸象. 首先,要设计这个应用,无论从界面,还是颜色搭配,以及功能,都是一个人完成. 也许,做独立开发人真的相当不容易. 因为,没有人帮忙给意见,而且,也没有 ...
- 凯尔卡C68全球版汽车电脑诊断仪
产品简介: C68汽车故障诊断仪是凯尔卡公司新推出的一款集经济.简约.稳定.耐用于一体的汽车诊断设备, 该产品采用了最新的智能移植技术,集成度高:C68车型覆盖广,测试功能强大.数据准确等优点, 是目 ...
- .net MVC 碰到的问题
1:问:回车会默认会触发页面从左边至右,从上到下索引位置第一的按钮事件.如何取消? 答:在不需要触发按钮事件的按钮中加一个属性:UseSubmitBehavior="false" ...
- Ext combox 动态 检索
spring mvc + extjs 免费下载 1 ext jar包 点击打开链接 2 ext 中文api 点击打开链接 java code: package com.paic.bbs.action; ...
- UVA 10025 (13.08.06)
The ? 1 ? 2 ? ... ? n = k problem Theproblem Given the following formula, one can set operators '+ ...
- Shell脚本[运算表达式,条件控制语句]
#!/bin/bash #你值得收藏的四则表达式运算. val1=1 val2=1 val3=1 val4=1 val5=1 val6=1 val7=1 let val1++ ((val2++)) v ...