Codeforces Round #459 (Div. 2) C 思维,贪心 D 记忆化dp

Codeforces Round #459 (Div. 2)

C. The Monster

题意:定义正确的括号串,是能够全部匹配的左右括号串。 给出一个字符串,有 (、)、 ? 三种字符, ? 可以当作 ( 可 ) 。 问这个字符串有多少个子串是正确的括号串。

tags:好考思维,想不到。。

预处理出每个字符向左向右最多可以匹配到哪里,再 O(n*n) 枚举所有区间,看是否符合条件。

//  C
#include<bits/stdc++.h>
using namespace std;
#pragma comment(linker, "/STACK:102400000,102400000")
#define rep(i,a,b) for (int i=a; i<=b; ++i)
#define per(i,b,a) for (int i=b; i>=a; --i)
#define mes(a,b)  memset(a,b,sizeof(a))
#define INF 0x3f3f3f3f
#define MP make_pair
#define PB push_back
#define fi  first
#define se  second
typedef long long ll;
const int N = 5005;

int len, l[N], r[N];
char s[N];
int main()
{
    scanf("%s", s+1);
    len = strlen(s+1);
    rep(i,1,len)
    {
        r[i] = len+1;
        int cnt = 0;
        rep(j,i,len)
        {
            if(s[j]==')') --cnt;
            else ++cnt;
            if(cnt<0) { r[i]=j; break; }
        }
    }
    per(i,len,1)
    {
        l[i] = 0;
        int cnt = 0;
        per(j,i,1)
        {
            if(s[j]=='(') --cnt;
            else ++cnt;
            if(cnt<0) { l[i]=j; break; }
        }
    }
    ll  ans = 0;
    rep(i,1,len)
    {
        for(int j=i+1; j<=len; j+=2)
        {
            if(r[i]>j && l[j]<i) ++ans;
        }
    }
    printf("%lld
", ans);

    return 0;
}
View Code

D. MADMAX

题意:给出一个DAG图,每条边有一个字母。两个人轮流走,每一次走过的边不能小于对方上一步走过的边。求两个人分别从点 i、j 出发,先手的胜负。

tags: dp[i][j][pre] 表示先手在点 i,后手在点 j ,且上一步的边是 pre 的情况下,先手胜就为 1,后手胜就为0 。

假设点 i 有边edge 可以到 to ,那么如果有 dp[j][to][edge] = 0,则 dp[i][j][pre] = 1 。

如果没有这样的点 to,那么  dp[i][j][pre] = 0。

当然,dp 肯定要记忆化的。

//  D
#include<bits/stdc++.h>
using namespace std;
#pragma comment(linker, "/STACK:102400000,102400000")
#define rep(i,a,b) for (int i=a; i<=b; ++i)
#define per(i,b,a) for (int i=b; i>=a; --i)
#define mes(a,b)  memset(a,b,sizeof(a))
#define INF 0x3f3f3f3f
#define MP make_pair
#define PB push_back
#define fi  first
#define se  second
typedef long long ll;
const int N = 105;

int n, m, G[N][N], dp[N][N][30], mx[N];
int solve(int i, int j, int pre)
{
    if(dp[i][j][pre]!=-1) return dp[i][j][pre];
    if(i==j)  return dp[i][j][pre]=0;
    if(mx[i]==-1) return dp[i][j][pre]=0;
    if(mx[i] > mx[j]) return dp[i][j][pre]=1;
    else
    {
        rep(to,1,n)
            if(G[i][to]!=-INF && G[i][to]>=pre)
            {
                if(solve(j, to, G[i][to])==0) return dp[i][j][pre]=1;
            }
    }
    return dp[i][j][pre]=0;
}
int main()
{
    scanf("%d%d", &n, &m);
    mes(dp, -1);  mes(mx, -1);
    rep(i,1,n) rep(j,1,n) G[i][j]=-INF;
    int u, v;  char ch;
    rep(i,1,m)
    {
        scanf("%d%d%*c%c", &u, &v, &ch);
        G[u][v] = ch-'a'+1;
    }
    rep(i,1,n)
    {
        int mx1=-1;
        rep(j,1,n) mx1=max(mx1, G[i][j]);
        mx[i] = mx1;
    }
    rep(i,1,n)
    {
        rep(j,1,n)
            if(solve(i, j, 0)) putchar('A');
            else putchar('B');
        puts("");
    }

    return 0;
}
View Code
原文地址:https://www.cnblogs.com/sbfhy/p/8394886.html