当前位置:编程学习 > C/C++ >>

HDU 4753 Fishhead’s Little Game (博弈+记忆话搜索)

题意:给你一个4*4的格子16个点,两个人博弈,每次可以添加一条边,当添加一条边后围成1*1的正方形时就加一分,现在已经给你n个回合,问你到最后谁将得的分最高(两个人都是很聪明,每一步都是最优的)。
 
题解:因为12<=n<=24,所以剩下的边最多只有12条,用状态压缩即可(2^12)
 
dp[i]表示,S中放了边的状态为i的情况下,先走还能获得的最大分数。
 
每次dfs维护一个剩余的分数sum,表示当前状态下能获得的最大分数,dp[s]=max(sum-走一步后对手获得的最大分数)
 
注意一点他们两的得分之和为9,因为只有9个1*1的正方形。
 
 
 
AC代码:
 
 
#include <iostream>  
#include <cstdio>  
#include <cstring>  
#include <string>  
#include <cstdlib>  
#include <cmath>  
#include <vector>  
#include <list>  
#include <deque>  
#include <queue>  
#include <iterator>  
#include <stack>  
#include <map>  
#include <set>  
#include <algorithm>  
#include <cctype>  
using namespace std;  
  
#define si1(a) scanf("%d",&a)  
#define si2(a,b) scanf("%d%d",&a,&b)  
#define sd1(a) scanf("%lf",&a)  
#define sd2(a,b) scanf("%lf%lf",&a,&b)  
#define ss1(s)  scanf("%s",s)  
#define pi1(a)    printf("%d\n",a)  
#define pi2(a,b)  printf("%d %d\n",a,b)  
#define mset(a,b)   memset(a,b,sizeof(a))  
#define forb(i,a,b)   for(int i=a;i<b;i++)  
#define ford(i,a,b)   for(int i=a;i<=b;i++)  
  
typedef __int64 LL;  
const int N=22;  
const int M=1000007;  
const int INF=0x3f3f3f3f;  
const double PI=acos(-1.0);  
const double eps=1e-7;  
  
struct node  
{  
    int x,y;  
}w;  
  
int n;  
int edge[N][N],dp[M],use[N];  
vector<node> mp;  
  
int 易做图(int a,int b)  
{  
    int sum=0;  
    if(a>b) swap(a,b);  
    if((b-a)==1)    //横着的  
    {  
        if(a>=1&&a<=4)  
        {  
            int aa=a+4,bb=b+4;  
            if(edge[aa][a]&&edge[aa][bb]&&edge[bb][b])  
                sum++;  
        }  
        else if(a>=13&&a<=16)  
        {  
            int aa=a-4,bb=b-4;  
            if(edge[aa][a]&&edge[aa][bb]&&edge[bb][b])  
                sum++;  
        }  
        else  
        {  
            int aa=a+4,bb=b+4;  
            if(edge[aa][a]&&edge[aa][bb]&&edge[bb][b])  
                sum++;  
            aa=a-4,bb=b-4;  
            if(edge[aa][a]&&edge[aa][bb]&&edge[bb][b])  
                sum++;  
        }  
    }  
    else    //竖着的  
    {  
        if(a%4==1)  
        {  
            int aa=a+1,bb=b+1;  
            if(edge[aa][a]&&edge[aa][bb]&&edge[bb][b])  
                sum++;  
        }  
        else if(a%4==0)  
        {  
            int aa=a-1,bb=b-1;  
            if(edge[aa][a]&&edge[aa][bb]&&edge[bb][b])  
                sum++;  
        }  
        else  
        {  
            int aa=a+1,bb=b+1;  
            if(edge[aa][a]&&edge[aa][bb]&&edge[bb][b])  
                sum++;  
            aa=a-1,bb=b-1;  
            if(edge[aa][a]&&edge[aa][bb]&&edge[bb][b])  
                sum++;  
        }  
    }  
    return sum;  
}  
  
int dfs(int now,int st,int last)  
{  
    if(now>=25)//结束  
        return 0;  
  
    if(dp[st]!=-1)//记忆话搜索  
        return dp[st];  
  
    int ma=0;  
    for(int i=0;i<mp.size();i++)  
    {  
        if(use[i])  continue;  
        int x=mp[i].x,y=mp[i].y;  
  
        edge[x][y]=edge[y][x]=1;  
        use[i]=1;  
        ma=max(ma,last-dfs(now+1,st|(1<<i),last-易做图(x,y)));  
        use[i]=0;  
        edge[x][y]=edge[y][x]=0;  
    }  
  
    dp[st]=ma;  
    return ma;  
}  
  
int main()  
{  
//    freopen("input.txt","r",stdin);  
    int T,ca=0;  
    si1(T);  
    while(T--)  
    {  
        int tom=0,jerry=0;  
        mset(edge,0);  
        si1(n);  
        ford(i,1,n)  
        {  
            int a,b;  
            si2(a,b);  
            edge[a][b]=edge[b][a]=1;  
            int k=易做图(a,b);  
            if(i&1) tom+=k;  
            else jerry+=k;  
        }  
  
        mp.clear();  
        ford(i,1,16)    //统计剩下的边  
            ford(j,i+1,16)  
            {  
                if(edge[i][j])  continue;  
                if((j-i)==1&&i%4!=0){w.x=i;w.y=j;mp.push_back(w);}  
                if((j-i)==4){w.x=i;w.y=j;mp.push_back(w);}  
            }  
        mset(dp,-1);  
        mset(use,0);  
        if((n+1)<=24)   //tom+jerry=9  
        {  
            if((n+1)&1)  
            {  
                tom+=dfs(n+1,0,9-tom-jerry);  
                jerry=9-tom;  
            }  
            else  
            {  
                jerry+=dfs(n+1,0,9-jerry-tom);  
                tom=9-jerry;  
            }  
        }  
        printf("Case #%d: %s\n",++ca,tom>jerry?"Tom200":"Jerry404");  
    }  
  
    return 0;  
}  

 

 
补充:软件开发 , C++ ,
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,