洛谷 1005 JZOJ 1181 矩阵取数游戏#区间dp#

本文介绍了一种通过动态规划解决矩阵取数游戏的方法,该游戏的目标是在遵循特定规则的情况下获得最大得分。文章给出了状态转移方程,并提供了一段C++代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目描述

帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的n∗mn*mnm的矩阵,矩阵中的每个元素aija_{ij}aij均为非负整数。游戏规则如下:

1.每次取数时须从每行各取走一个元素,共nnn个。mmm次后取完矩阵所有元素;

2.每次取走的各个元素只能是该元素所在行的行首或行尾;

3.每次取数都有一个得分值,为每行取数的得分之和,每行取数的得分 = 被取走的元素值∗2i*2^i2i,其中iii表示第i次取数(从1开始编号);

4.游戏结束总得分为mmm次取数得分之和。

帅帅想请你帮忙写一个程序,对于任意矩阵,可以求出取数后的最大得分。


题目分析

采用区间型dp
状态转移方程:
f[i][i+len]f[i][i+len]f[i][i+len]表示取数iiii+leni+leni+len的最大值
f[i][i+len]=max(2∗f[i+1][i+len]+2∗a[i],2∗f[i][i+len−1]+2∗a[i+len])f[i][i+len]=max(2*f[i+1][i+len]+2*a[i],2*f[i][i+len-1]+2*a[i+len])f[i][i+len]=max(2f[i+1][i+len]+2a[i]2f[i][i+len1]+2a[i+len])
取左边和取右边的最大值,用类似于秦九韶算法代替2的乘方。请注意使用高精度或__int128int128int128


代码

#include <cstdio>
#include <cctype>
#include <cstring>
#include <algorithm>
#define lll __int128
using namespace std;
int n,m,a[82]; lll f[82][82],ans;
int in(){
    int ans=0; char c=getchar();
    while (!isdigit(c)) c=getchar();
    while (isdigit(c)) ans=ans*10+c-48,c=getchar();
    return ans;
}
void print(lll ans){
    if (!ans) return; 
    else print(ans/10);
    putchar(ans%10+48);
}
lll dp(int *a){
    memset(f,0,sizeof(f));
    for (int len=0;len<=m;len++)
    for (int i=1;i+len<=m;i++)
    f[i][i+len]=max(2*f[i+1][i+len]+2*a[i],2*f[i][i+len-1]+2*a[i+len]);//动态规划
    return f[1][m];
}
int main(){
    n=in(); m=in();
    for (int i=1;i<=n;i++){
        for (int j=1;j<=m;j++) a[j]=in();
        ans+=dp(a);
    }
    if (ans) print(ans); else putchar('0');
    return 0;
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值