[CF377C]Captains Mode

题目

传送门

题解

刚开始我以为这是个贪心,然后打了这样一个代码

inline void Solve(){
    int pts=1,ans=0;
    char opt[5];int team;
    while(m--){
        scanf("%s %d",opt,&team);
        if(opt[0]=='p')ans+=(team==1?1:-1)*val[pts];
        ++pts;
    }writc(ans,'\n');
}

然后 \(WA\) 穿了......

显然贪心是不对的,因为如果一个人有很多个操作,他在 \(ban\) 的回合,不一定会 \(ban\) 掉战力最高的英雄

如何解决这个问题?

由于每个队长执行的操作是保证最优的,我们可以定义 dfs(now,s) 为执行到操作 \(now\),剩下的英雄状态为 \(s\) 时,当前操作的队伍能让差变得多大(返回值),那么,对于一个操作 \(i\),如果操作 \(i\)\(i+1\) 是同一队执行,那么差值显然是叠加,否则,最大差值肯定是作差。

为什么这样设计?因为我们要保证每一队都进行最优选择。

在很多类似的题目中,都保证双方执行最优解时,我们都可以这样进行处理,这是一个很好的方法——线交替先后手地位,用作和或作差对解进行叠加。

对于每一个操作,我们可以暴力枚举我们应该 \(pick/ban\) 掉哪个英雄,为降低复杂度,我们可以定义 \(f[i][j]\)dfs(i,j) 的返回值。

而我们有四个操作,\(pick,ban,miss\space pick,miss\space ban\),但是对于 \(pick\) 的回合,选择一定比不选择更优,对于 \(ban\),如果是 \(miss\space ban\) 也相当于 \(ban\) 掉一个最差的英雄,对结果不影响,也就是说,我们只需要考虑 \(pick\)\(ban\) 两种操作即可。

对于时间复杂度的分析,因为两队都进行最优选择,那么一定不会选择差的英雄,也相当于,只有前 \(m\) 个战力最大的英雄有用,那么时间复杂度为 \(\mathcal O(20\times 20\times 2^{20})=\mathcal O(419430400)\)?(为什么还可以过)

代码

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

#define rep(i,__l,__r) for(signed i=(__l),i##_end_=(__r);i<=i##_end_;++i)
#define fep(i,__l,__r) for(signed i=(__l),i##_end_=(__r);i>=i##_end_;--i)
#define erep(i,u) for(signed i=tail[u],v=e[i].to;i;i=e[i].nxt,v=e[i].to)
#define writc(a,b) fwrit(a),putchar(b)
#define mp(a,b) make_pair(a,b)
#define ft first
#define sd second
typedef long long LL;
// typedef pair<int,int> pii;
typedef unsigned long long ull;
typedef unsigned uint;
#define Endl putchar('\n')
// #define int long long
// #define int unsigned
// #define int unsigned long long

#define cg (c=getchar())
template<class T>inline void read(T& x){
    char c;bool f=0;
    while(cg<'0'||'9'<c)f|=(c=='-');
    for(x=(c^48);'0'<=cg&&c<='9';x=(x<<1)+(x<<3)+(c^48));
    if(f)x=-x;
}
template<class T>inline T read(const T sample){
    T x=0;char c;bool f=0;
    while(cg<'0'||'9'<c)f|=(c=='-');
    for(x=(c^48);'0'<=cg&&c<='9';x=(x<<1)+(x<<3)+(c^48));
    return f?-x:x;
}
template<class T>void fwrit(const T x){//just short,int and long long
    if(x<0)return (void)(putchar('-'),fwrit(-x));
    if(x>9)fwrit(x/10);
    putchar(x%10^48);
}
template<class T>inline T Max(const T x,const T y){return x>y?x:y;}
template<class T>inline T Min(const T x,const T y){return x<y?x:y;}
template<class T>inline T fab(const T x){return x>0?x:-x;}
inline int gcd(const int a,const int b){return b?gcd(b,a%b):a;}
inline void getInv(int inv[],const int lim,const int MOD){
    inv[0]=inv[1]=1;for(int i=2;i<=lim;++i)inv[i]=1ll*inv[MOD%i]*(MOD-MOD/i)%MOD;
}
inline LL mulMod(const LL a,const LL b,const LL mod){//long long multiplie_mod
    return ((a*b-(LL)((long double)a/mod*b+1e-8)*mod)%mod+mod)%mod;
}

const int MAXN=100;
const int MAXM=20;
const int MAXSIZE=(1<<20);
const int INF=(1<<30)-1;

int a[MAXN+5],n,m,all;

char opt[MAXM+5][5];
int team[MAXM+5];

inline bool cmp(const int x,const int y){return x>y;}

inline void Init(){
    n=read(1);
    rep(i,0,n-1)a[i]=read(1);
    sort(a,a+n,cmp);
    n=m=read(1);
    all=(1<<m)-1;
    rep(i,0,m-1)scanf("%s %d",opt[i],&team[i]);
}

int f[MAXM+5][MAXSIZE+5];
bool vis[MAXM+5][MAXSIZE+5];

int Dfs(const int step,const int s){
    // printf("Now step == %d, s == %d\n",step,s);
    if(vis[step][s])return f[step][s];
    vis[step][s]=true;
    f[step][s]=-INF;
    if(opt[step][0]=='p'){
        rep(i,0,m-1)if((s>>i)&1){
            if(step==m-1)f[step][s]=Max(f[step][s],a[i]);
            else if(team[step]==team[step+1])
                f[step][s]=Max(f[step][s],a[i]+Dfs(step+1,s^(1<<i)));
            else f[step][s]=Max(f[step][s],a[i]-Dfs(step+1,s^(1<<i)));
        }
    }else{
        rep(i,0,m-1)if((s>>i)&1){
            if(step==m-1)f[step][s]=Max(f[step][s],0);
            else if(team[step]==team[step+1])
                f[step][s]=Max(f[step][s],Dfs(step+1,s^(1<<i)));
            else f[step][s]=Max(f[step][s],-Dfs(step+1,s^(1<<i)));
        }
    }return f[step][s];
}

#define sign(x) ((x)==1?1:-1)

signed main(){
    Init();
    writc(sign(team[0])*Dfs(0,all),'\n');
    return 0;
}
posted @ 2020-08-05 20:47  Arextre  阅读(228)  评论(0编辑  收藏  举报