HDU 4753 Fishhead’s Little Game (对抗搜索)

来源:互联网 发布:乐器模拟软件排行 编辑:程序博客网 时间:2024/05/01 23:06

题意:在3*3的方格中,有4*4=16个点,标号分别为1~16,A、B两人轮流玩游戏,每次可以添加一条边(相邻节点),如果恰好能够凑成一个边长为1的正方形则得一分,两个的话得2分。现在给定两人已经连接的n条边后,求最终格局谁会胜。


因为总计只有24条边,而且只能剩下0--12条边,所以状态压缩记录好剩下还没走好的步数,dp[i]表示状态i下,当前玩家能获得的最大分数。

如何处理连边,方法多多,随意YY..............本人用vis[a][b] 表示,为0表示a,b无边,为1表示有边但是游戏进行到当前此边未使用,为2表示有边并且此边已经使用..................


#include <iostream>#include <algorithm>#include <cmath>#include<functional>#include <cstdio>#include <cstdlib>#include <cstring>#include <string>#include <vector>#include <set>#include <map>#include <queue>#include <stack>#include <climits>//形如INT_MAX一类的#define MAX 100005#define INF 0x7FFFFFFF#define REP(i,s,t) for(int i=(s);i<=(t);++i)#define ll long long#define mem(a,b) memset(a,b,sizeof(a))#define mp(a,b) make_pair(a,b)#define L(x) x<<1#define R(x) x<<1|1# define eps 1e-5using namespace std;int n,sumA,sumB;int dp[5555],used[30];int vis[30][30];struct node {    int a,b;} ed[30];int num;void init() {    sumA = 0;    sumB = 0;    num = 0;    memset(used,0,sizeof(used));    memset(dp,-1,sizeof(dp));    memset(vis,0,sizeof(vis));    for(int i=0; i<=3; i++) {        for(int j=1; j<=3; j ++) {            int a = i * 4 + j;            int b = i * 4 + j + 1;            vis[a][b] = 1;            vis[b][a] = 1;        }    }    for(int i=1; i<=12; i++) {        int a = i;        int b = i + 4;        vis[a][b] = 1;        vis[b][a] = 1;    }}int cal() { //计算到目前已经得到的分数    int cnt = 0;    for(int i=0; i<3; i++) {        for(int j=1; j<=3; j++) {            int a = i * 4 + j;            int b = a + 1;            int c = a + 4;            int d = c + 1;            if(vis[a][b] == 2 && vis[a][c] == 2 && vis[c][d] == 2 && vis[b][d] == 2 ) cnt ++;        }    }    return cnt ;}int dfs(int step,int cur) {    if(step == 25 || cur == 0) return 0;    int buff = 0;    for(int i=0; i<num; i++) {        if(used[i] == 1) buff = buff | (1 << i);    }    if(dp[buff] != -1) return dp[buff];    int cmp = 0;    for(int i=0; i<num; i++) {        if(used[i] == 1) continue;        used[i] = 1;        vis[ed[i].a][ed[i].b] = 2;        vis[ed[i].b][ed[i].a] = 2;        int t = cal();        cmp = max(cmp,cur - dfs(step + 1,9 - t));        used[i] = 0;        vis[ed[i].a][ed[i].b] = 1;        vis[ed[i].b][ed[i].a] = 1;    }    return dp[buff] = cmp;}int main() {    int T;    cin >> T;    int ca = 1;    while(T--) {        init();        scanf("%d",&n);        int cnt = 0,a,b;        for(int i=1; i<=n; i++) {            scanf("%d%d",&a,&b);            vis[a][b] = 2;            vis[b][a] = 2;            int t = cal();            if(i % 2 == 1) sumA += t - cnt;            else sumB += t - cnt;            cnt = t;        }        printf("Case #%d: ",ca++);        if(sumA >= 5) {            printf("Tom200\n");            continue;        }        if(sumB >= 5) {            printf("Jerry404\n");            continue;        }        //把剩余的边统计出来        for(int i=1; i<=15; i++) {            for(int j=i+1; j<=16; j++) {                if(vis[i][j] == 1) {                    ed[num].a = i;                    ed[num].b = j;                    num++;                }            }        }        int cur = 9 - sumA - sumB;        if((n+1) % 2 == 1) {            sumA += dfs(n+1,cur);            sumB = 9 - sumA;        } else {            sumB += dfs(n+1,cur);            sumA = 9 - sumB;        }        //cout << sumA << ' ' << sumB << endl;        if(sumA > sumB) printf("Tom200\n");        else printf("Jerry404\n");    }    return 0;}


原创粉丝点击