南昌邀请赛网络赛 D.Match Stick Game(dp)

南昌邀请赛网络赛 D.Match Stick Game

题目传送门

题目就会给你一个长度为n的字符串,其中\(1<n<100\)。这个字符串是一个表达式,只有加减运算符,然后输入的每一个字符都是可以由若干个火柴棒拼接而成的。
现在在不改变每个数的位数,数的总数以及运算符的个数的前提下,可以对火柴棒重新拼接。询问最后可以拼接出来的最大值是多少。
这个自己看下题目可能要清楚一些= =

?
每一个字符都是由若干个火柴棒构成的,我们可以考虑类似于背包的思路来求解。
因为每个数的位数最后都没发生变化,所以我们可以预处理出\(f[i][j]\)以及\(g[i][j]\),分别表示\(i\)位数由\(j\)根火柴构成的最大/最小值。
因为这里除开火柴棒个数之外还涉及到了加减号,所以我们定义\(dp(i,j,0/1)\)为前\(i\)个数字,用了\(j\)根火柴棒,并且当前这个数字前面是\(-\)还是\(+\)。
由于数据范围比较小,所以考虑加和减两种情况进行合理转移就行了。
详见代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1005;
int n, T;
char s[N] ;
int len[N] ;
ll dp[105][N][2], f[105][N], g[105][N];
int trans1[10] = {0, 0, 1, 7, 4, 5, 9, 8} ;
int trans2[10] = {0, 0, 1, 7, 4, 2, 0, 8} ;
int num ;
int main() {
    cin >> T;
    for(int i = 1; i <= 10; i++)
        for(int j = 2; j < N; j++) {
            g[i][j] = 1e14;
            f[i][j] = f[i][j - 1] ;
            for(int k = 2; k <= 7; k++) {
                if(j - k >= 0) f[i][j] = max(f[i - 1][j - k] * 10 + trans1[k], f[i][j]) ;
            }
        }
    for(int i = 1; i <= 10; i++)
        for(int j = 2; j < N; j++) {
            if(i == 1) {
                g[i][j] = 1;
                continue ;
            }
            g[i][j] = g[i][j - 1] ;
            for(int k = 2; k <= 7; k++) {
                if(j - k >= 0) g[i][j] = min(1ll * g[i - 1][j - k] * 10 + 1ll * trans2[k], g[i][j]) ;
            }
        }
    while(T--) {
        memset(dp, 0, sizeof(dp)) ;
        scanf("%d", &n);
        scanf("%s", s + 1);
        int cnt = 0, x = 0, num = 0;
        for(int i = 1; i <= n; i++) {
            if(s[i] == '+' || s[i] == '-') {
                len[++num] = cnt ;
                cnt = 0;
                if(s[i] == '+') x += 2;
                else x += 1;
            } else {
                cnt++;
                if(s[i] == '1') x += 2 ;
                else if(s[i] == '7') x += 3 ;
                else if(s[i] == '4') x += 4 ;
                else if(s[i] == '5' || s[i] == '2' || s[i] == '3') x += 5;
                else if(s[i] == '0' || s[i] == '6' || s[i] == '9') x += 6;
                else x += 7;
            }
        }
        len[++num] = cnt;
        for(int i = 2; i <= x; i++) dp[1][i][0] = dp[1][i][1] = f[len[1]][i] ;
        for(int i = 2; i <= num; i++) {
            for(int j = 2; j <= x; j++) {
                for(int k = 2; k <= j; k++) {
                    if(j - k - 2 >= 2) {
                        dp[i][j][1] = max(dp[i][j][1], dp[i - 1][j - k - 2][1] + f[len[i]][k]) ;
                        dp[i][j][1] = max(dp[i][j][1], dp[i - 1][j - k - 2][0] + f[len[i]][k]) ;
                    }
                    if(j - k - 1 >= 2) {
                        dp[i][j][0] = max(dp[i][j][0], dp[i - 1][j - k - 1][0] - g[len[i]][k]) ;
                        dp[i][j][0] = max(dp[i][j][0], dp[i - 1][j - k - 1][1] - g[len[i]][k]) ;

                    }
                }
            }
        }
        ll ans = 0;
        ans = max(ans, max(dp[num][x][0], dp[num][x][1])) ;
        cout << ans << '\n';
    }
    return 0 ;
}

原文地址:https://www.cnblogs.com/heyuhhh/p/10753434.html

时间: 2024-10-08 09:17:32

南昌邀请赛网络赛 D.Match Stick Game(dp)的相关文章

2019.4.20南昌邀请赛网络预选赛

The Preliminary Contest for ICPC China Nanchang National Invitational 他人博客题解:戳这里 原文地址:https://www.cnblogs.com/QLU-ACM/p/10743125.html

2019南昌邀请赛网络预选赛 M. Subsequence

•题意 给出一个只包含小写字母的串 s 和n 个串t,判断t[i]是否为串 s 的子序列: 如果是,输出"YES",反之,输出"NO": •思路 可以把s串中每一个字母的位置预处理出来.(由于总长度是1e5,可能有26个字母,用数组存[26][100000]显然是不可能的,所以就用vector动态分配一下(QwQ) 然后设置一个指针cur,指向当前字母的位置. 再开一个数组记录一下使用后的每个字母的最后一个位置,为了避免每次从第一个开始找. •代码 #include

2019南昌icpc网络赛 I题 分块套BIT

https://nanti.jisuanke.com/t/41356 对于带修的二维数点,可以bit套主席树,也可CDQ三维偏序 但是最后我选择分块套BIT暴力... 复杂度为$m(blocksize*logn+blocknum)$ 显然,如果按照$\sqrt{n}$分块,并不是最优的 我们可以适当的增加块的大小,减少块的数量,让$blocksize*logn=blocknum$ 在这个题中,大概就是$\sqrt{1e6}$到$\sqrt{2e6}$之间吧 #include<bits/stdc+

2019ICPC南昌邀请赛现场赛A题 - Attack(斯坦纳树)

题意: 给出一张图,求让\(4\)对点相互可以到达的最小边权值.仅要求一对之间,一对与另外一对可到达也可不到达. 分析: 斯坦纳树裸题,众所周知斯坦纳树仅能求出这\(4\)对点(关键点)的连通状况,如这\(4\)对点相互都连通,某点和某点连通等.然而让这\(4\)对点连通符合题目要求,但不一定是最优解(我可以让每对点直接相连),所以我们要对斯坦纳树求出的\(dp\)数组进行子集\(dp\)才能得到最优解. #include <bits/stdc++.h> using namespace std

ICPC2018徐州网络赛 Hard to prepare(dp)

Hard to prepare 28.63% 1000ms 262144K After Incident, a feast is usually held in Hakurei Shrine. This time Reimu asked Kokoro to deliver a Nogaku show during the feast. To enjoy the show, every audience has to wear a Nogaku mask, and seat around as a

2016 年沈阳网络赛---QSC and Master(区间DP)

题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=5900 Problem Description Every school has some legends, Northeastern University is the same. Enter from the north gate of Northeastern University,You are facing the main building of Northeastern Universi

个人心情:又是一年网络赛

前天在群里看到,网络赛快开始了,第一次觉得假期好曼城,是不是因为在工作的原因啊,有种度日如年的感觉哈哈.话说真相拿出时间来好好学习一下. 上一张ACM网络赛时间表 赛区(官方网站) 邀请赛 网络赛 现场赛 备注 牡丹江赛区牡丹江师范学院   9.7 12:00~17:00 在HDOJ举行浙江大学命题 10.11~12浙江大学命题   鞍山赛区辽宁科技大学   9.13 12:00~17:00 在HDOJ举行清华大学命题 10.18~19清华大学命题   西安赛区西北工业大学 陕西邀请赛 报名截止

2019 ICPC 南昌网络赛

2019 ICPC 南昌网络赛 比赛时间:2019.9.8 比赛链接:The 2019 Asia Nanchang First Round Online Programming Contest 总结 // 史上排名最高一次,开场不到两小时队友各A一题加水题共四题,排名瞬间升至三四十名 // 然后后三小时就自闭了,一题都没有突破...最后排名211 hhhh ? ? B. Fire-Fighting Hero 题意 队友做的,待补. ? AC代码 #include<cstdio> #includ

ACM-ICPC 2019南昌网络赛I题 Yukino With Subinterval

ACM-ICPC 2019南昌网络赛I题 Yukino With Subinterval 题目大意:给一个长度为n,值域为[1, n]的序列{a},要求支持m次操作: 单点修改 1 pos val 询问子区间中某个值域的数的个数,连续的相同数字只记为一个.(即统计数字段的个数) 2 L R x y 数据范围: 1 ≤ n,m ≤ 2×10^5 1 ≤ a[i] ≤ n 解题思路: 连续重复的数字只记一次.所以考虑将每个数字段除第一个出现外的数字都删去(记为0).在读入操作的时候暴力模拟,同时维护