[Codeforces Gym] 100162A Box Game 博弈+二分图匹配

来源:互联网 发布:s3c2440a数据手册 编辑:程序博客网 时间:2024/05/17 01:20

第一次做交互题,真是留下了心理阴影

先说题目,转化一下模型大概是一个n维棋盘博弈,每次只能移动到坐标相邻的点,已经访问过的点不能重复访问

先求先手必胜还是必败,然后和计算机交互

一道简化很多很多很多的题目:

http://www.lydsy.com/JudgeOnline/problem.php?id=2463

结论:

将初始点拿掉以后,对棋盘黑白染色,若与初始点颜色相反的点个数 >  与初始点颜色相同的个数,则先手必胜,否则先手必败。

至于方案:显然对手所处在的颜色个数小于等于我所在的点颜色的个数,对于每个对手点匹配一个下一个点,每次交互的时候顺着匹配边走就可以了。

注意:

1、dinic能过

2、把结论仔细理解透彻以后再开始写,否则后果不堪设想。

3、map会爆空间

我想是时候去学学匈牙利算法了


#include <iostream>#include <cstdio>#include <queue>#include <cstring>#define N 100050#define W 16#define INF (1<<29)using namespace std;int n,siz,cnt,S,T,g[2],stdpos;int vis[N],h[N],c[N],pp[N],ban[N];int fc[N],cur[N];bool ans;struct Node{ int x[W];}w,p,id;int v(Node p) {int s=0 , t=1;for (int i=1;i<=n;i++) s += (p.x[i]-1) * t , t *= (w.x[i]);return s+1;} struct Edge{int a,b,v,next,o1,o2;void print() {printf("debug::edge  %d %d %d %d %d\n",a,b,v,o1,o2);}}e[50*N];void add(int a,int b,int v,int o1,int o2) {e[++cnt].a = a;   e[cnt].b = b;   e[cnt].v = v;e[cnt].next = h[a];   h[a] = cnt;e[cnt].o1 = o1;   e[cnt].o2 = o2;return ;}void add_Node(int a,int b,int v,int o1,int o2) {add(a,b,1-v,o1,o2); add(b,a,v,0,0);}bool aq(Node x) {for (int i=1;i<=n;i++) if (x.x[i]<1 || x.x[i]>w.x[i]) return 0;return 1;}void color(Node s) {g[0]=g[1]=0;for (int i=1;i<=siz;i++) vis[i] = 0;queue<Node> q; q.push(s); vis[v(s)]=1;while (!q.empty()) {Node now=q.front(); q.pop();int vnow = v(now); ;if (v(now) != v(p)) g[ c[vnow] ]++;for (int i=1;i<=n;i++)for (int j=-1;j<=1;j+=2) {Node nxt=now; nxt.x[i] += j;if (!aq(nxt)) continue;int vxt = v(nxt);if (vis[vxt]) continue;c[vxt]=c[vnow]^1;vis[vxt] = 1;q.push(nxt);}}return ;}void build(Node s) {cnt = 1;for (int i=0;i<=siz+5;i++) vis[i] = pp[i] = 0;queue<Node> q; q.push(s); vis[ v(s) ] = 1;while (!q.empty()) {Node now=q.front(); q.pop();int vnow = v(now);for (int i=1;i<=n;i++) for (int j=-1;j<=1;j+=2) {Node nxt=now; nxt.x[i] += j;if (!aq(nxt)) continue;int vxt = v(nxt);if (c[vnow] == stdpos && !ban[vnow] && !ban[vxt]) {if (!pp[vnow] && !pp[vxt]) {pp[vnow] = pp[vxt] = 1;add_Node(vnow,vxt,1,i,j);} else {add_Node(vnow,vxt,0,i,j);}}if (vis[vxt]) continue;vis[vxt]=1; q.push(nxt);}}S = siz+1; T = siz+2;for (int i=1;i<=siz;i++) if (!ban[i]){if (c[i] == stdpos) add_Node(S,i,pp[i],0,0);elseadd_Node(i,T,pp[i],0,0);}return ;}#define cp e[i].v#define B e[i].bbool BFS() {    bool flag = 0;        for (int i=0;i<=siz+5;i++) fc[i]=0; fc[S] = 1;    for (int i=0;i<=siz+5;i++) cur[i] = h[i];    queue<int> q; q.push(S);     while (!q.empty()) {        int u = q.front(); q.pop();        if (u == T) flag = 1;        for (int i=h[u];i;i=e[i].next)             if (e[i].v>0 && !fc[B]) {                fc[B] = fc[u]+1;                q.push(B);            }    }    return flag;}int DFS(int u,int flow) {    if (u == T) return flow;    int f = flow , g = 0 , tmp = 0;    for (int &i=cur[u];i;i=e[i].next)        if (cp>0 && fc[B]==fc[u]+1 && ( tmp=DFS(B,min(cp,f)) ) > 0) {            e[i  ].v -= tmp;             e[i^1].v += tmp;            f -= tmp; g += tmp;        }    return g;}bool X() {int x; char ch;scanf("%d %c",&x,&ch);if (ch == '?') return 0;if (ch == '+') p.x[x]++; else p.x[x]--;return 1;}void Y() {int o1=ans?0:INF,o2=ans?0:INF;for (int i=h[v(p)];i;i=e[i].next) if (e[i].v==0 && e[i].o2) {o1=e[i].o1; o2=e[i].o2; break;}p.x[o1] += o2;printf("%d %c\n",o1,o2>0 ? '+' : '-'); fflush(stdout);}int main() {while (1) {//init();scanf("%d",&n); if (n == 0) break;for (int i=1;i<=15;i++) if (i<=n) id.x[i]=1; else id.x[i]=0;p=w=id;for (int i=1;i<=n;i++) scanf("%d",&w.x[i]) , w.x[i]++;for (int i=1;i<=n;i++) scanf("%d",&p.x[i]) , p.x[i]++;siz = v(w);ans = false;//for (int i=1;i<=n;i++) if (w.x[i]%2 == 0) ans = true;color(id);int idc = c[ v(p) ];if (g[idc^1] > g[idc]) ans = 1; else ans = 0; //1Alice先手 , 0Bob后手 if (ans==1) {stdpos = idc;printf("Alice\n"); fflush(stdout);build(id);while (BFS()) DFS(S,INF);Y();} else {stdpos = idc^1;printf("Bob\n"); fflush(stdout);ban[v(p)] = true;build(id);while (BFS()) DFS(S,INF);}while (X()) Y();//for (int i=2;i<=cnt;i+=2) e[i].print();for (int i=0;i<=siz+10;i++)pp[i]=vis[i]=h[i]=c[i]=ban[i]=0;for (int i=1;i<=cnt;i++)e[i]=(Edge){0,0,0,0,0,0};}return 0;}


0 0
原创粉丝点击