高精度-四位压缩(结构体重载运算符)+DP(洛谷P1005-方格取数)

洛谷P1005方格取数
这是一道典型的dp题
且根据题意得行与行之间没有任何的联系,只需找到每一行的最优解相加就得出最终答案。
设dp数组为f[maxn][maxn],并将每一行的数据储存在数组a[maxn]中,
分析题意dp规则为:
f[q][w]=max(f[q-1][w]+pow(2,m-(w-q+1))*a[q-1],f[q][w+1]+pow(2,m-(w-q+1))a[w+1]);
但是提交后会发现只能通过60%的数据原因就下面:
这是该题的数据范围
其中1<=n,m<=80,也就意味着要计算2的80次方,而c++中longlong的范围为范围:-922 3372 0368 5477 5808 ~ 922 3372 0368 5477 5807 (922
10^16) ,所以就必须要调用高精算法(其实用Java中的大数类也能实现)
高精度模板之前已经发了:
高精度模板(结构体重载运算符(+ - *))
最后一步:通过pow2()函数预先算出2的幂,并储存在数组p[maxn]中,以便调用

#include <iostream>
#include <algorithm>
#include <cmath>
#include <vector>
#include <string>
#include <cstring>
#include <cstdio>
#define maxn 86
#define mod 10000
using namespace std;
int n,m,a[maxn];
struct BI{
int l[505],len;
BI(){
    memset(l,0,sizeof(l));
    len=0;
}
void print(){
    printf("%d",l[len]);
for(int q=len-1;q>0;q--){
if(l[q]==0){
printf("0000");
continue;
}
for(int w=10;w*l[q]<mod;w*=10){
printf("0");
}
printf("%d",l[q]);
}}}f[maxn][maxn],p[maxn],sum;
BI operator +(const BI &a,const BI &b){
BI c;c.len=max(a.len,b.len);int x=0;
for(int q=1;q<=c.len;q++){
c.l[q]=a.l[q]+b.l[q]+x;
x=c.l[q]/mod;
c.l[q]%=mod;
}
if(x>0){c.l[++c.len]=x;}
return c;
}
BI operator *(const BI &a,int b){
BI c;c.len=a.len;int x=0;
for(int q=1;q<=c.len;q++){
c.l[q]=a.l[q]*b+x;
x=c.l[q]/mod;
c.l[q]%=mod;
}
while(x>0){
c.l[++c.len]=x%mod;
x/=mod;
}
return c;
}
BI  max(const BI &a,const BI &b){
BI c=a;
if(a.len!=b.len)
c=a.len>b.len?a:b;
else{
for(int q=a.len;q>0;q--){
if(a.l[q]!=b.l[q]){
c=a.l[q]>b.l[q]?a:b;
break;
}}}
return c;
}
void pow2(){
p[0].l[1]=1;p[0].len=1;
for(int q=1;q<=m+2;q++){
p[q]=p[q-1]*2;
}
}
BI ys(int a[]){
BI maxx;
maxx.len=0;
for(int q=1;q<=m;q++){
for(int w=m;w>=q;w--){
f[q][w]=max(f[q-1][w]+p[m-(w-q+1)]*a[q-1],f[q][w+1]+p[m-(w-q+1)]*a[w+1]);
}
f[q][q]=f[q][q]+p[m]*a[q];
maxx=max(maxx,f[q][q]);
}
return maxx;
}
int main()
{
    scanf("%d%d",&n,&m);
    pow2();
    int a[maxn];
    for(int q=0;q<n;q++){
    memset(f,0,sizeof(f));
    memset(a,0,sizeof(a));
    for(int w=1;w<=m;w++){
    scanf("%d",&a[w]);
    }
    sum=sum+ys(a);
    }
    sum.print();
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值