您的位置:首页 > 其它

Codeforces Round #334 C. Alternative Thinking (dp)

2015-12-03 02:59 399 查看
题意:

给定一个长度为105的01序列,现要求翻转一个非空子串,就是串内0变1,1变0,求最长交替01子序列的长度,比如01010或者10101,就是5

分析:

这题可以找规律贪心,我直接xjb dp的

考虑状态dp[i][0/1][0/1]:=以第i位结尾,且这位是0/1,序列有没有翻转过的最长交替01子序列

转移就毕竟麻烦,要考虑前面的相反的最大值,用一个前缀max,同时还要维护状态取到的位置来判断是不是可以继续翻转,总之很麻烦

还好1A了−−写完了之后只是觉得dp还是弱,虽然很清楚怎么做了,但真的应该想的无比清楚再写,dp真不差这2分钟手速,一旦稍微晕了,debug的代价更高

这题还可以证明,不翻转不比翻转更优,假设不翻转是个最优状态,那么完全翻转整个串的结果是相同的,假设不成立,所以原命题成立

证明这个主要是我交的时候不小心max了没有翻转的状态,嘛所以不要慌着resubmit,仔细想想是不是真的错了

代码:

//
//  Created by TaoSama on 2015-12-01
//  Copyright (c) 2015 TaoSama. All rights reserved.
//
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <string>
#include <set>
#include <vector>

using namespace std;
#define pr(x) cout << #x << " = " << x << "  "
#define prln(x) cout << #x << " = " << x << endl
const int N = 1e5 + 10, INF = 0x3f3f3f3f, MOD = 1e9 + 7;

int n, dp
[2][2], b
[2][2], wh
[2][2];
char s
;

void getMax(int &x, int y) {
x = max(x, y);
}

int main() {
#ifdef LOCAL
freopen("C:\\Users\\TaoSama\\Desktop\\in.txt", "r", stdin);
//  freopen("C:\\Users\\TaoSama\\Desktop\\out.txt","w",stdout);
#endif
ios_base::sync_with_stdio(0);

while(scanf("%d", &n) == 1) {
scanf("%s", s + 1);
memset(dp, 0, sizeof dp);
memset(b, 0, sizeof b);
memset(wh, 0, sizeof wh);
for(int i = 1; i <= n; ++i) {
int p = s[i] - '0';
//得到之前的状态
b[i][p ^ 1][0] = b[i - 1][p ^ 1][0];
b[i][p][0] = b[i - 1][p][0];
b[i][p][1] = b[i - 1][p][1];
b[i][p ^ 1][1] = b[i - 1][p ^ 1][1];
wh[i][p ^ 1][0] = wh[i - 1][p ^ 1][0];
wh[i][p][0] = wh[i - 1][p][0];
wh[i][p][1] = wh[i - 1][p][1];
wh[i][p ^ 1][1] = wh[i - 1][p ^ 1][1];

getMax(dp[i][p][0], b[i][p ^ 1][0] + 1);
getMax(dp[i][p][1], b[i][p ^ 1][1] + 1);

if(wh[i][p][1] == i - 1)
getMax(dp[i][p ^ 1][1], b[i][p][1] + 1);
getMax(dp[i][p ^ 1][1], b[i][p][0] + 1);

//更新前缀max
if(dp[i][p][0] > b[i][p][0]) {
b[i][p][0] = dp[i][p][0];
}
if(dp[i][p][1] > b[i][p][1]) {
b[i][p][1] = dp[i][p][1];
}
if(dp[i][p ^ 1][1] > b[i][p ^ 1][1]) {
b[i][p ^ 1][1] = dp[i][p ^ 1][1];
wh[i][p ^ 1][1] = i;
}

//          printf("dp[%d][%d][%d] = %d\n", i, 0, 0, dp[i][0][0]);
//          printf("dp[%d][%d][%d] = %d\n", i, 0, 1, dp[i][0][1]);
//          printf("dp[%d][%d][%d] = %d\n", i, 1, 0, dp[i][1][0]);
//          printf("dp[%d][%d][%d] = %d\n", i, 1, 1, dp[i][1][1]);
}

int ans = 0;
for(int i = 1; i <= n; ++i) {
getMax(ans, max(dp[i][0][0], dp[i][0][1]));
getMax(ans, max(dp[i][1][0], dp[i][1][1]));
}
printf("%d\n", ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  dp