zoukankan      html  css  js  c++  java
  • Comet OJ

    题意

    https://www.cometoj.com/contest/35/problem/C?problem_id=1498

    思路

    这题要用到一种比较小众的状压方法(没见过的话可能一时比较难想到)。

    首先观察题面,发现可以把一个人有另一个人没有的点数都视作同一种(转化一),然后点数之间也可以任意转化(转化二),不影响结果,经过如上转化,可以将任意情况转化为两方各有一些相同点数的手牌,然后不同点数的手牌只有一种或没有。

    (感觉说的好乱啊,举个栗子吧...

    [egin{array}{} &2,3,5,6,6|1,2,5,5,7\ o&2,5,X,X,X|2,5,5,Y,Y ext{(转化一)}\ o&1,2,X,X,X|1,2,2,Y,Y ext{(转化二)}\ o&1,2,3,3,3|1,2,2,4,4 ext{(转化二)}\ end{array} ]

    然后就是状压的部分,由于两人最多只能有 (8) 张手牌。而手牌之间只有相同不相同才有影响,于是把手牌变成 (01) 序列,即相邻不同的用 (01) 相区别。

    (感觉还是不清楚啊,继续举栗子吧...

    (1,2,3,3,3 o 10111)

    $ 1,2,2,4,4 o 10011$

    当然为了表示有没有对方没有对牌,还需另外记一个布尔值。

    最后,任何时刻不得打出上次打出的牌,所以再记一个整数表示上一次打出的手牌标号,为了方便起见,这个标号是相对于本方而言的。然后如果因为是第一回合,或者对方打了本方没有的牌等情况,没有这个限制的话,这个整数就记为 (8) (因为本方手牌最多从 (0) 标号到 (7) 嘛)。

    细节还是很多的,据说出题人和验题人的代码也都很长,我还是赛后膜改一天改出了下面这个代码,感触最深的就是把位操作封函数后会好写很多。

    代码

    #include<bits/stdc++.h>
    #define FOR(i,x,y) for(int i=(x),i##END=(y);i<=i##END;++i)
    #define DOR(i,x,y) for(int i=(x),i##END=(y);i>=i##END;--i)
    template<typename T,typename _T>inline bool chk_min(T &x,const _T y){return y<x?x=y,1:0;}
    template<typename T,typename _T>inline bool chk_max(T &x,const _T y){return x<y?x=y,1:0;}
    typedef long long ll;
    int dp[(1<<8)+5][2][(1<<8)+5][2][9];	//0:lose  1:draw  2:win
    int bin[(1<<8)+5];							//dp[a][b][c][d][e]
    int T;										//a为本方手牌
    											//b为本方有没有对方没有的牌
    inline int bit_take(int B,int l,int r)		//c为对方手牌
    {											//d为对方有没有本方没有的牌
    	return B&(((1<<(r+1))-1)^((1<<l)-1));	//e为上一次出的手牌标号(相对本方而言)
    }
    inline int bit_erase(int B,int x)
    {
    	return bit_take(B,0,x-1)|(bit_take(B,x+1,bin[B])>>1);
    }
    inline int bit_reverse(int B,int l,int r)
    {
    	return B^(((1<<(r+1))-1)^((1<<l)-1));
    }
    inline int bit_swapping(int B,int l1,int r1,int r2)
    {
    	int B1=bit_take(B,l1,r1),B2=bit_take(B,r1+1,r2);
    	return (B^B1^B2)|(B1<<(r2-r1))|(B2>>(r1-l1+1));
    }
    
    int get_dp(int A,bool a,int B,int b,int las)
    {
    	int &res=dp[A][a][B][b][las];
    	if(~res)return res;
    	else if(B==0)
    	{
    		if(las==8)return res=1;
    		else return res=0;
    	}
    	res=0;
    	int cnta=-1,cntb=-1;
    	int ra[9],rb[9];
    	DOR(i,bin[A],0)if(i==bin[A]||((A>>i&1)!=(A>>(i+1)&1)))ra[++cnta]=i;
    	DOR(i,bin[B],0)if(i==bin[B]||((B>>i&1)!=(B>>(i+1)&1)))rb[++cntb]=i;
    	ra[cnta+1]=rb[cntb+1]=-1;
    	FOR(i,0,cnta)
    	{
    		int l=ra[i+1]+1,r=ra[i];
    		if(i!=las)
    		{
    			int nA=bit_erase(A,r),na=a,nB=B,nb=b,nlas;
    			if(l==r)
    			{
    				nA=bit_reverse(nA,0,r-1);
    				if(a&&i==cnta)na=0,nlas=8;
    				else if(i==cntb)nb=1,nlas=cntb;
    				else
    				{
    					int x=rb[cntb+1]+1,y=rb[i+1],z=rb[i];
    					nB=bit_reverse(nB,x,y);
    					if((cntb-b-i)&1)nB=bit_reverse(nB,y+1,z);
    					nB=bit_swapping(nB,x,y,z);
    					if(b)nlas=8;
    					else nlas=cntb,nb=1;
    				}
    			}
    			else
    			{
    				if(a&&i==cnta)nlas=8;
    				else nlas=i;
    			}
    			chk_max(res,2-get_dp(nB,nb,nA,na,nlas));
    		}
    	}
    	return res;
    }
    
    void solve()
    {
    	int n;
    	int A[25]={0},B[25]={0};
    	scanf("%d",&n);
    	FOR(i,1,n)
    	{
    		int x;
    		scanf("%d",&x);
    		A[x]++;
    	}
    	FOR(i,1,n)
    	{
    		int x;
    		scanf("%d",&x);
    		B[x]++;
    	}
    	int X=0,Y=0,x=0,y=0;
    	bool cur=1;
    	FOR(i,1,20)
    	{
    		if(A[i]&&!B[i])x+=A[i];
    		else if(!A[i]&&B[i])y+=B[i];
    		else if(A[i]&&B[i])
    		{
    			FOR(j,1,A[i])X=(X<<1)|cur;
    			FOR(j,1,B[i])Y=(Y<<1)|cur;
    			cur^=1;
    		}
    	}
    	FOR(i,1,x)X=(X<<1)|cur;
    	FOR(i,1,y)Y=(Y<<1)|cur;				//转化手牌
    	int res=get_dp(X,x!=0,Y,y!=0,8);
    	if(res==0)puts("dreamoon wins");
    	else if(res==1)puts("Draw");
    	else if(res==2)puts("AA wins");
    }
    
    int main()
    {
    	bin[1]=0;FOR(i,2,1<<8)bin[i]=bin[i>>1]+1;
    	memset(dp,-1,sizeof(dp));
    	int T;
    	scanf("%d",&T);
    	while(T--)solve();
    	return 0;
    }
    
  • 相关阅读:
    Eclipse配置Maven详细教程
    Spring MVC 搭建web项目示例
    C# Action 和Func
    C# params 用法简介
    WPF绘图性能问题
    C# EventWaitHandle用法
    C#5.0 异步编程async/await用法
    通过Struts2Web应用框架深入理解MVC
    Java过滤器—Filter用法简介
    WPF内嵌CEF控件,与JS交互
  • 原文地址:https://www.cnblogs.com/Paulliant/p/11136964.html
Copyright © 2011-2022 走看看