bign+dp 矩阵取数

状态转移方程可以直接用dp[i][j]=max(dp[i+1,j]+a[i],dp[i,j-1]+a[j])*(2^k)),但是还要算2^k次方,可以先用数组储存2的方幂,但不可避免高精度乘法,如果只是*2的话可以用加法代替

逆向思考,自内而外,用f[i,j]表示从i取到j的最大值,状态转移方程便为f[i,j]:=max(f[i+1,j]+a[i],f[i,j-1]+a[j])*2 ,相当于每到下一层都把上一层乘了2,越在内层,乘2的次数越多,这样我们就免于高精度乘法了

简略代码如下:

struct bigint {int a[40];};
int m,n;
bigint a[81],res,f[81][81],k1,k2;

bigint add(bigint k,bigint l)
{
    bigint j;
    memset(j.a, 0, sizeof(j.a));
    for(int i=1;i<=k.a[0]||i<=l.a[0];i++) j.a[i]=k.a[i]+l.a[i];
    j.a[0]=k.a[0]>l.a[0]?k.a[0]:l.a[0];
    for(int i = 1; i <= j.a[0]; i++){
        j.a[i+1]+=j.a[i]/10;
        j.a[i]%=10;
    }
    if(j.a[j.a[0]+1]>0)    j.a[0]++;
    return j;
}
////////////////////////////////////////////////////////////
bigint cmp(bigint k,bigint l)
{
    if(k.a[0]>l.a[0]) return k;
    if(k.a[0]<l.a[0]) return l;
    if(k.a[0]==l.a[0]) for(int i=k.a[0];i>=1;i--){
        if(k.a[i]>l.a[i]) return k;
        if(k.a[i]<l.a[i]) return l;
    }
    return l;
}
//////////////////////////////////////////////////////////////
void init()
{
    memset(a,0,sizeof(a));
    for(int i=1;i<=m;i++){
        scanf("%d",&a[i].a[1]);
        a[i].a[0]=1;
        while(a[i].a[a[i].a[0]]>=10)
        {//a[0]表示a的位数,将输入的存在[1]中的数分散到a[1,2..]中去
            a[i].a[a[i].a[0]+1]=a[i].a[a[i].a[0]]/10;
            a[i].a[a[i].a[0]]%=10;
            a[i].a[0]++;
        }
    }
}
/////////////////////////////////////////////////////////////
void solve()
{
    memset(f,0,sizeof(f));
    for(int i=1;i<=m;i++) f[i][i]=add(a[i],a[i]);
    for(int i=m;i>=1;i--)
        for(int j=i+1;j<=m;j++){
            k1=add(f[i+1][j],a[i]);
            k2=add(f[i][j-1],a[j]);
            f[i][j]=cmp(k1,k2);
            f[i][j]=add(f[i][j],f[i][j]);
        }
    res=add(res,f[1][m]);
}
/////////////////////////////////////////////////////////////
int main()
{
    scanf("%d%d",&n,&m);
    res.a[0]=1;
    for(int i=1;i<=n;++i){
        init();
        solve();
    }
    //output
    for (int i=res.a[0];i>0;i--)
        printf("%d",res.a[i]);
    cout<<endl;
     return 0;
}

bign+dp 矩阵取数

时间: 2024-10-05 06:32:24

bign+dp 矩阵取数的相关文章

51Nod 1083 矩阵取数问题(矩阵取数dp,基础题)

1083 矩阵取数问题 基准时间限制:1 秒 空间限制:131072 KB 分值: 5 难度:1级算法题 一个N*N矩阵中有不同的正整数,经过这个格子,就能获得相应价值的奖励,从左上走到右下,只能向下向右走,求能够获得的最大价值. 例如:3 * 3的方格. 1 3 3 2 1 3 2 2 1 能够获得的最大价值为:11. Input 第1行:N,N为矩阵的大小.(2 <= N <= 500) 第2 - N + 1行:每行N个数,中间用空格隔开,对应格子中奖励的价值.(1 <= N[i] 

1083 矩阵取数问题(DP)

1083 矩阵取数问题 基准时间限制:1 秒 空间限制:131072 KB 分值: 5 难度:1级算法题  收藏  关注 一个N*N矩阵中有不同的正整数,经过这个格子,就能获得相应价值的奖励,从左上走到右下,只能向下向右走,求能够获得的最大价值. 例如:3 * 3的方格. 1 3 3 2 1 3 2 2 1 能够获得的最大价值为:11. Input 第1行:N,N为矩阵的大小.(2 <= N <= 500) 第2 - N + 1行:每行N个数,中间用空格隔开,对应格子中奖励的价值.(1 <

NOIP2007矩阵取数[DP|高精度]

题目描述 帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的n*m的矩阵,矩阵中的每个元素aij均为非负整数.游戏规则如下: 1.每次取数时须从每行各取走一个元素,共n个.m次后取完矩阵所有元素: 2.每次取走的各个元素只能是该元素所在行的行首或行尾: 3.每次取数都有一个得分值,为每行取数的得分之和,每行取数的得分 = 被取走的元素值*2^i,其中i表示第i次取数(从1开始编号): 4.游戏结束总得分为m次取数得分之和. 帅帅想请你帮忙写一个程序,对于任意矩阵,可以求出取数后的最大得分. 输入输

dp+高精度(洛谷1005 矩阵取数游戏NOIP 2007 提高第三题)

帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的n*m的矩阵,矩阵中的每个元素aij均为非负整数.游戏规则如下: 1.每次取数时须从每行各取走一个元素,共n个.m次后取完矩阵所有元素: 2.每次取走的各个元素只能是该元素所在行的行首或行尾: 3.每次取数都有一个得分值,为每行取数的得分之和,每行取数的得分 = 被取走的元素值*2^i,其中i表示第i次取数(从1开始编号): 4.游戏结束总得分为m次取数得分之和. 帅帅想请你帮忙写一个程序,对于任意矩阵,可以求出取数后的最大得分. 输入格式: 输入

【日常学习】【区间DP+高精】codevs1166 矩阵取数游戏题解

题目来自NOIP2007TG3 如果在考场上我现在已经歇菜了吧 今天一整天的时间全部投在这道题上,收获不小. 先上题目 题目描述 Description [问题描述] 帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的n*m 的矩阵,矩阵中的每个元素aij均 为非负整数.游戏规则如下: 1. 每次取数时须从每行各取走一个元素,共n个.m次后取完矩阵所有元素: 2. 每次取走的各个元素只能是该元素所在行的行首或行尾: 3. 每次取数都有一个得分值,为每行取数的得分之和,每行取数的得分= 被取走的元素

1166 矩阵取数游戏[区间dp+高精度]

1166 矩阵取数游戏 2007年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题解 题目描述 Description [问题描述]帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的n*m 的矩阵,矩阵中的每个元素aij均为非负整数.游戏规则如下:1. 每次取数时须从每行各取走一个元素,共n个.m次后取完矩阵所有元素:2. 每次取走的各个元素只能是该元素所在行的行首或行尾:3. 每次取数都有一个得分值,为每行取数的得分之和,每行取数的得分

[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

TYVJ 矩阵取数 Label:高精度+dp

题目描述 帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的n*m的矩阵,矩阵中的每个元素aij均为非负整数.游戏规则如下: 1.每次取数时须从每行各取走一个元素,共n个.m次后取完矩阵所有元素: 2.每次取走的各个元素只能是该元素所在行的行首或行尾: 3.每次取数都有一个得分值,为每行取数的得分之和,每行取数的得分 = 被取走的元素值*2^i,其中i表示第i次取数(从1开始编号): 4.游戏结束总得分为m次取数得分之和. 帅帅想请你帮忙写一个程序,对于任意矩阵,可以求出取数后的最大得分. 输入输

洛谷 P1005 矩阵取数游戏 题解

此文为博主原创题解,转载时请通知博主,并把原文链接放在正文醒目位置. 题目链接:https://www.luogu.org/problem/show?pid=1005 题目描述 帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的n*m的矩阵,矩阵中的每个元素aij均为非负整数.游戏规则如下: 1.每次取数时须从每行各取走一个元素,共n个.m次后取完矩阵所有元素: 2.每次取走的各个元素只能是该元素所在行的行首或行尾: 3.每次取数都有一个得分值,为每行取数的得分之和,每行取数的得分 = 被取走的元