• CodeForces1312E 区间DP


    题意

    伊珂丝是个爱玩游戏的少女。经常因为贪玩而耽误了咖啡馆的工作,也因此常被店长吐槽。不过真到了干活的时候,伊珂丝也是当仁不让的!

    这次伊珂丝又来找店长PK了,如果店长赢下这局,伊珂丝就答应在咖啡馆里干一天活儿,你能帮帮店长,战胜伊珂丝吗?

    游戏规则如下:

    游戏中一开始有n个数字排成一排,这n(<=500)个数的大小都在1~1000之间。
    每次可以选择两个 相邻且相等 的数字,将它们合并成一个数字。
    合并后的数字是原来的数字 +1,合并后数字个数 -1。
    如果没有满足合并条件的数,则游戏结束。最后剩下的数字越少越好。
    现在给出n与这些数字的信息,你能帮助店长算一算,最好成绩是剩下几个数字?

    解法

    看数据范围和题意不难想到是区间DP,唯一值得讨论的是dp数组的维护形式,这里给出的形式是用一个node表示dp的节点,包含num(区间内元素数量), l(区间左值), r(区间右值),以num越小的node越优先来更新dp
    tips:

    • 看似这样的表示方法不能唯一表示一个节点,形如 2 2 2的区间既可以表示为num = 2, l = 2, r = 3,也可以表示为num = 2, l = 3, r = 2,但是对于这道题来说不关键
    • 对于样例3 2 2 2而言,将由[1,3] + [4,4]来更新到全局,对于2 2 2 3而言,将有[1,1] + [2,4]来更新到全局,实际上总有一种区间合并的方式来更新到num最小的全局答案,与区间[2,2,2]计算的l,r是否唯一无关

    代码

    #include<bits/stdc++.h>
    using namespace std;
    #define PII pair<int,int>
    #define fi first
    #define se second
    #define mp make_pair
    #define LL long long
    const int maxn = 500 + 10;
    const int mod = 1e9 + 7; 
    int N,M,S;
    int a[maxn];
    struct node {
        int l,r,num;
    };
    node dp[maxn][maxn];
    int main(){
        int N; scanf("%d",&N);
        for(int i = 1; i <= N ; i ++) {
            for(int j = 1; j <= N; j ++) {
                dp[i][j].num = 0x3f3f3f3f;
            }
        }
        for(int i = 1; i <= N ; i ++) {
            scanf("%d", &a[i]);
            dp[i][i].num = 1;
            dp[i][i].l = dp[i][i].r = a[i];
        }
        for(int len = 1; len <= N; len ++) {
            for(int l = 1; l + len - 1 <= N; l ++) {
                int r = l + len - 1;
                for(int k = l ; k <= r - 1; k ++) {
                    int num = dp[l][k].num + dp[k + 1][r].num;
                    int L = dp[l][k].l,R = dp[k + 1][r].r;
                    if(dp[l][k].r == dp[k + 1][r].l) {
                        num--;
                        if(dp[l][k].num == 1) L++;;
                        if(dp[k + 1][r].num == 1) R++;            
                    }
                    if(num < dp[l][r].num) {
                        dp[l][r].num = num;
                        dp[l][r].l = L;
                        dp[l][r].r = R;
                    }    
                }
            }
        }
        printf("%d",dp[1][N].num);
        return 0;
    }
    
    // 5      4 3 2 1 1
    // 9      4 3 2 1 1 2 3 4 5
    
  • 相关阅读:
    单例模式
    grails2.3.11第二课
    grails2.3.11第一课
    【安全】requests和BeautifulSoup小试牛刀
    【解决】国内访问github过慢
    基于Ubuntu14.10的Hadoop+HBase环境搭建
    基于adt-bundle的Android开发环境搭建
    【解决】SAE部署Django1.6+MySQL
    【解决】Django项目废弃SQLite3拥抱MySQL
    【OpenGL】画立方体
  • 原文地址:https://www.cnblogs.com/Hugh-Locke/p/13764279.html
Copyright © 2020-2023  润新知