Gray (dp 或 乱搞)

10.10

思路
用dp[i][0/1]表示前i位在第i位时能得到的最大分数。

标解:

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

const int N = 200010;

int n, a[N];
char s[N];
int f[N][2];

int main(){
    freopen("gray.in","r",stdin);
    freopen("gray.out","w",stdout);
        scanf("%s", s); n = strlen(s);
        for(int i = 0; i < n; i++) scanf("%d", &a[i]);
        memset(f, 0, sizeof(f));
        if(s[0] == '1' || s[0] == '?') f[0][1] = a[0];
        for(int i = 1; i < n; i++){
            if((s[i] == '1' || s[i] == '?') && (s[i-1] == '0' || s[i-1] == '?'))
                f[i][1] = std::max(f[i][1], f[i-1][0] + a[i]);
            if((s[i] == '1' || s[i] == '?') && (s[i-1] == '1' || s[i-1] == '?'))
                f[i][1] = std::max(f[i][1], f[i-1][1]);
            if((s[i] == '0' || s[i] == '?') && (s[i-1] == '1' || s[i-1] == '?'))
                f[i][0] = std::max(f[i][0], f[i-1][1] + a[i]);
            if((s[i] == '0' || s[i] == '?') && (s[i-1] == '0' || s[i-1] == '?'))
                f[i][0] = std::max(f[i][0], f[i-1][0]);
        }
        printf("%d\n", max(f[n-1][0], f[n-1][1]));

    return 0;
}

本人的乱搞(大模拟)
细节问题就自己看啦(估计也没人写这么蠢的方法了)

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#define LL long long
#define N 200010
using namespace std;

inline int read(){
    int x = 0, f = 1; char ch = getchar();
    while(ch < '0' || ch > '9'){ if(ch == '-') f = -1; ch = getchar(); }
    while(ch >= '0' && ch <= '9'){ x = x * 10 + ch - '0'; ch = getchar(); }
    return x * f;
}

int a[N], ans=0;
char s[N];

int main(){
    freopen ("gray.in", "r", stdin);
    freopen ("gray.out", "w", stdout);
    scanf("%s", s+1);
    int len = strlen( s+1 );
    for(register int i=1; i<=len; i++){
        a[i] = read();
        if(s[i] != '?'){
            if(i == 1) ans += (s[i] - '0') * a[i];
            else ans += ((s[i] - '0') ^ (s[i-1] - '0')) * a[i];
        }
        else{
            int lf = s[i-1] - '0', rg, minn = a[i], S = 1, flag = 0; ans += a[i];
            if(i == 1) flag = 1;
            while(s[i+1] == '?') i++, scanf("%d", &a[i]), minn = min(minn, a[i]), S++, ans += a[i];
            rg = s[i+1] - '0';
            if(i == len) flag = 2;
            else scanf("%d", &a[++i]), ans += a[i], minn = min(minn, a[i]);
            if((S - (lf == rg)) % 2 != 0 && flag == 0) ans -= minn;
            if(flag == 1 && (S + rg) % 2 == 0) ans -= minn;
        }
    }
    printf("%d\n", ans);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值