1. 程式人生 > >ACM-ICPC 2018 徐州賽區網路預賽

ACM-ICPC 2018 徐州賽區網路預賽

題意:

每一輪有三種操作, 加上a 減去b 或者 取負 當且僅當 a, b, c 不為0時,對應的操作有效; 給出一個上界和一個下界 大於等於上界就是 Good Ending 小於等於下界 就是 Bad Ending 否則就是 Normal Ending 兩個人輪流操作,第一個人想要Good Ending 第二個人想要 Bad Ending  兩個人操作最優,求最後的結局

思路:

dp[i][j] 表示 第幾輪 數字是多少的時候 ,記憶化爆搜 ,因為數字在[−100,100]

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e3+7;
int n,m,k,l,a[maxn],b[maxn],c[maxn];
int dp[maxn][250];//dp[i][id[j]]表示第i輪的數字為j
map<int,int> id;
int up,down;
int dfs(int pos,int now)
{
    if(pos==n+1)
    {
        if(now>=k)
            return 2;
        else if(now>l)
            return 1;
        else
            return 0;
    }
    if(dp[pos][id[now]]!=-1)    return dp[pos][id[now]];
    if(pos&1)//奇數
    {
        int f=0;
        if(a[pos])  f=max(f,dfs(pos+1,min(now+a[pos],up)));
        if(b[pos])  f=max(f,dfs(pos+1,max(now+b[pos],down)));
        if(c[pos])  f=max(f,dfs(pos+1,-now));
        return dp[pos][id[now]]=f;
    }else{
        int f=2;
        if(a[pos])  f=min(f,dfs(pos+1,min(now+a[pos],up)));
        if(b[pos])  f=min(f,dfs(pos+1,max(now+b[pos],down)));
        if(c[pos])  f=min(f,dfs(pos+1,-now));
        return dp[pos][id[now]]=f;
    }
}
int main()
{
    int tot=0;
    up=100;
    down=-100;
    for(int i=-100;i<=100;i++)
        id[i]=++tot;
    scanf("%d%d%d%d",&n,&m,&k,&l);
    for(int i=1;i<=n;i++)
    {
        scanf("%d%d%d",&a[i],&b[i],&c[i]);
        b[i]=-b[i];
    }
    memset(dp,-1,sizeof dp);
    int f=dfs(1,m);
    if(f==2)
        printf("Good Ending\n");
    else if(f==1)
        printf("Normal Ending\n");
    else
        printf("Bad Ending\n");
    return 0;
}