zoukankan      html  css  js  c++  java
  • P1043 [NOIP2003 普及组] 数字游戏 题解(区间dp)

    转载 :https://www.luogu.com.cn/blog/zhoushuyu/solution-p1043

    题目链接

    题目思路

    总结一下这种类似DP题目的思路和技巧吧。

    1、破环成链。没有太多的技巧性,具体而言就是把数据存储两遍,使得环形的数据可以链式展开,便于我们去DP。

    但最后一定要记得扫一遍答案,取(F[i][i+N-1]; i:1->N)中的最大/小值。

    2、前缀和。这个东西并不是在所有情况下都适用,但使用起来真的很方便,可以把O(n)的复杂度优化为O(1)。不过只适用于需要把数据直接相加的地方,比如说这道题。

    3、初始化。这里实际上包括两点,一方面是在某些特殊情况下需要初始化,初始化为某特定值(比如本题只分成1段的时候)。另一方面也就是数组初始化,求最大值的时候根本不用管(因为初始默认为0),在求最小值的时候把数组全部赋初值为极大值就好啦。

    4、状态表达。一般来说可以用F[i][j]表示在区间[i,j]中怎么怎么样,但由于本题还加了一个分为几段的状态,就把数组直接加一维就好了。

    代码

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long  ll;
    #define fi first
    #define se second
    const int maxn=1e2+5,inf=0x3f3f3f3f;
    int n,m;
    int a[maxn];
    int dpma[maxn][maxn][10+5];
    int dpmi[maxn][maxn][10+5];
    int mod(int a){
       return (a%10+10)%10;
    }
    int main(){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++){//破环成链
            scanf("%d",&a[i]);
            a[i+n]=a[i];
        }
        for(int i=1;i<=2*n;i++){ //前缀和
            a[i]+=a[i-1];
        }
        memset(dpmi,0x3f,sizeof(dpmi));
        for(int i=1;i<=m;i++){
            for(int j=1;j<=2*n;j++){
                dpmi[j][j][i]=dpma[j][j][i]=mod(a[j]-a[j-1]);
            }
        }
        for(int i=1;i<=m;i++){
            for(int r=1;r<=2*n;r++){// 右端点
                for(int l=r;l>=1;l--){// 左端点
                    if(i==1){
                        dpma[l][r][i]=dpmi[l][r][i]=mod(a[r]-a[l-1]);
                        continue;
                    }
                    for(int mid=l;mid<r;mid++){ //中间端点
                        dpma[l][r][i]=max(dpma[l][r][i],dpma[l][mid][i-1]*mod(a[r]-a[mid])); //[mid+1,r]
                        dpmi[l][r][i]=min(dpmi[l][r][i],dpmi[l][mid][i-1]*mod(a[r]-a[mid]));
                    }
                }
            }
        }
        int ans1=inf,ans2=0;
        for(int i=1;i<=n;i++){
            ans1=min(ans1,dpmi[i][i+n-1][m]);
            ans2=max(ans2,dpma[i][i+n-1][m]);
        }
        printf("%d
    %d
    ",ans1,ans2);
        return 0;
    }
    
    
  • 相关阅读:
    Java 开发 gRPC 服务和客户端
    Springcloud中的region和zone的使用
    Spring Boot中使用AOP记录请求日志
    JDK1.8中的Lambda表达式和Stream
    机器学习之SVM
    机器学习之决策树
    【iOS开发】emoji表情的输入思路
    block为什么要用copy,runtime的简单使用
    swift和oc混编
    iOS之AFN错误代码1016(Error Domain=com.alamofire.error.serialization.response Code=-1016 "Request failed: unacceptable)
  • 原文地址:https://www.cnblogs.com/hunxuewangzi/p/14319076.html
Copyright © 2011-2022 走看看