洛谷P1043 数字游戏 划分dp入门

丁丁最近沉迷于一个数字游戏之中。这个游戏看似简单,但丁丁在研究了许多天之后却发觉原来在简单的规则下想要赢得这个游戏并不那么容易。游戏是这样的,在你面前有一圈整数(一共nn个),你要按顺序将其分为mm个部分,各部分内的数字相加,相加所得的mm个结果对1010取模后再相乘,最终得到一个数kk。游戏的要求是使你所得的k最大或者最小。

例如,对于下面这圈数字(n=4,m=2n=4,m=2):

要求最小值时,((2-1) \bmod 10)×((4+3) \bmod 10)=1×7=7((2−1)mod10)×((4+3)mod10)=1×7=7,要求最大值时,为((2+4+3) \bmod 10)×(-1 \bmod 10)=9×9=81((2+4+3)mod10)×(−1mod10)=9×9=81。特别值得注意的是,无论是负数还是正数,对1010取模的结果均为非负值。

丁丁请你编写程序帮他赢得这个游戏。

输入格式

输入文件第一行有两个整数,n(1≤n≤50)n(1≤n≤50)和m(1≤m≤9)m(1≤m≤9)。以下nn行每行有个整数,其绝对值\le 10^4≤104,按顺序给出圈中的数字,首尾相接。

输出格式

输出文件有22行,各包含11个非负整数。第11行是你程序得到的最小值,第22行是最大值。

输入输出样例

输入 #1

4 2
4
3
-1
2

输出 #1

7
81

题意:中文题意。

题目思路:

之前做过一个 划分回文的 划分dp,看到这个题之后没有反应过来,特此总结一下,划分dp

划分dp的基本dp思想:[l,r] 如何划分可以得到最优解,或者[l,r] 划分最少多少次可以满足条件..

基本状态转移

dp[l][r][j]  //代表 l,r 区间内 划分为 J 段的最优贡献

对于此题来说:

其中mod 为取余函数,其余的都是细节问题,比如说由于涉及到乘法,所以边界应该设为1,更简单的我们直接将一段的答案算出来,划分段数从2开始即可。

这题主要是用来总结一下 这个划分dp的思想

AC:

#pragma GCC optimize(2)
#include<bits/stdc++.h>
typedef long long ll;
const int maxn=1e6+5;
using namespace std;
const ll INF=1e13+7;
ll n,m;
ll num[205];
ll dp1[200][200][20];
ll dp2[200][200][20];
ll sum[205];
ll mod(ll x)
{
    return (x%10+10)%10;
}
void inint()
{
    scanf("%lld%lld",&n,&m);
    for(int i=1;i<=n;i++)
    {
        scanf("%lld",&num[i]);
        num[i+n]=num[i];
    }
    for(int i=1;i<=2*n;i++) sum[i]=sum[i-1]+num[i];
}
void work()
{
    //dp1[l][r][j]  i-k 分成 j段获得的最大值
    //dp1[l][r][j] = max dp[l][k][j-1]*(sum[r]-sum[k]);
    for(int l=1;l<=n;l++)
    {
        for(int r=l;r<=l+n-1;r++)//
        {
            dp1[l][r][1]=mod(sum[r]-sum[l-1]);
            dp2[l][r][1]=mod(sum[r]-sum[l-1]);
            for(int j=2;j<=m;j++)
            {
                ll temp1=INF,temp2=-INF;
                for(int k=l;k<r;k++)
                {
                    temp1=min(temp1,dp2[l][k][j-1]*mod(sum[r]-sum[k]));
                    temp2=max(temp2,dp1[l][k][j-1]*mod(sum[r]-sum[k]));
                }
                dp1[l][r][j]=temp2;
                dp2[l][r][j]=temp1;
            }
        }
    }
    ll resmin=INF,resmax=0;
    for(int i=1;i<=n;i++)
    {
        resmax=max(resmax,dp1[i][i+n-1][m]);
        resmin=min(resmin,dp2[i][i+n-1][m]);
    }
    printf("%lld\n%lld\n",resmin,resmax);
}
int main()
{
    inint();
    work();
    return 0;
}

/**

**/

 

全部评论

相关推荐

不愿透露姓名的神秘牛友
07-11 12:31
以前小时候我最痛恨出轨、偷情的人,无论男女,为什么会出轨?现在我成了自己最讨厌的人,没想到分享的东西在牛客会被这么多人看,大家的评价都很中肯,我也认同,想过一一回复,但我还是收声了,我想我应该说说这件事,这件事一直压在我心里,是个很大的心结,上面说了人为什么出轨,我大概能明白了。我们大一下半年开始恋爱,开始恋爱,我给出了我铭记3年的承诺,我对她好一辈子,我永远不会背叛,我责任心太重,我觉得跟了我,我就要照顾她一辈子,我们在一起3年我都没有碰过她,她说往东我就往东,她说什么我做什么,她要我干什么,我就干什么!在学校很美好,中途也出过一些小插曲,比如男闺蜜、男闺蜜2号等等等。但我都强迫她改掉了,我...
牛客刘北:两个缺爱的人是没有办法好好在一起的,但世界上哪有什么是非对错?你后悔你们在一起了,但是刚刚在一起的美好也是真的呀,因为其他人的出现,你开始想要了最开始的自己,你的确对不起自己,21岁的你望高物远,你完全可以不谈恋爱,去过你想要的生活,你向往自由,在一起之后,你要想的不是一个人,而是两个人,你不是变心了,就像你说的,你受够了,你不想包容了,冷静几天是你最优的选择,爱人先爱己。
社会教会你的第一课
点赞 评论 收藏
分享
05-29 09:02
门头沟学院 Java
点赞 评论 收藏
分享
06-08 22:25
门头沟学院 Java
从零开始的转码生活:这hr不会打开手机不分青红皂白给所有人群发这句话,过一会再给所有人再发一遍,这肯定会有重复的,不管,再过一会再发一遍
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务