hdu 5208 Where is Bob (数位dp,k进制树合并)

题意:

Alice和一个人玩游戏(艹Bob没了),假设另外一个是Bob吧!他们各自从区间A和区间B中取一个数,然后两个数做异或运算,现在Alice想让整个数尽量打,Bob想让这个数尽量小。问最后的数是多少。

题解:

这题首先要懂这个博弈,表示真心没懂这个博弈,听了凡神指点,虐有明白。如果知道了这个博弈就能做这题了。我们设置dp[pos][f1][f2][f3][f4]表示在某个位pos并且边界条件f1f2f3f4,能取得的那个数最大是多少(对于Alice来考虑的),这样在数位dp的位处理的时候考虑Bob就根据贪心来想,因为Bob想让这个值最小,那么肯定尽量要跟Alice去的一样,于是根据这样数位dp求解。

这题跟博弈挂上钩的确有点吊,出题人脑洞略大。

#include<iostream>
#include<math.h>
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<vector>
#include<queue>
#include<map>
#include<set>
#define B(x) (1<<(x))
using namespace std;
typedef long long ll;
void cmax(int& a,int b){ if(b>a)a=b; }
void cmin(int& a,int b){ if(b<a)a=b; }
void cmax(ll& a,ll b){ if(b>a)a=b; }
void cmin(ll& a,ll b){ if(b<a)a=b; }
void add(int& a,int b,int mod){ a=(a+b)%mod; }
void add(ll& a,ll b,ll mod){ a=(a+b)%mod; }
const int oo=0x3f3f3f3f;
const int MOD=100007;
const int maxn=100005;
const int maxm=23336666;
int dp[40][2][2][2][2];
int L1,R1,L2,R2;

int dfs(int pos,int f1,int f2,int f3,int f4){
    if(pos<0) return 0;
    if(dp[pos][f1][f2][f3][f4]!=-1) return dp[pos][f1][f2][f3][f4];
    int x1= f1 ? ((L1>>pos)&1) : 0;
    int y1= f2 ? ((R1>>pos)&1) : 1;
    int x2= f3 ? ((L2>>pos)&1) : 0;
    int y2= f4 ? ((R2>>pos)&1) : 1;
    int res=0;
    for(int i=x1;i<=y1;i++){
        if(x2==y2){//Bob只能选0或1时
            cmax(res,dfs(pos-1,f1&&i==x1,f2&&i==y1,f3,f4)+(i^x2)*B(pos));
        }else{//Bob 0 1都可选,但是肯定选和Alice一样的
            cmax(res,dfs(pos-1,f1&&i==x1,f2&&i==y1,f3&&i==x2,f4&&i==y2));
        }
    }
    return dp[pos][f1][f2][f3][f4]=res;
}

int main(){
    //freopen("E:\\read.txt","r",stdin);
    int T,n;
    scanf("%d",&T);
    for(int cas=1;cas<=T;cas++){
        scanf("%d %d %d %d",&L1,&R1,&L2,&R2);
        memset(dp,-1,sizeof dp);
        printf("Case #%d: %d\n",cas,dfs(30,1,1,1,1));
    }
    return 0;
}







你可能感兴趣的:(hdu 5208 Where is Bob (数位dp,k进制树合并))