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

本文探讨了一道复杂的博弈论问题,通过构建图模型并利用图算法解决该问题。介绍了如何将问题转化为n维棋盘上的游戏,并使用图染色、匹配等技巧来判断胜负及构造解决方案。

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

先说题目,转化一下模型大概是一个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);
		else
			add_Node(i,T,pp[i],0,0);
	}
		
	return ;
}

#define cp e[i].v
#define B e[i].b
bool 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;
}


当前提供的引用内容并未提及关于Codeforces比赛M1的具体时间安排[^1]。然而,通常情况下,Codeforces的比赛时间会在其官方网站上提前公布,并提供基于不同时区的转换工具以便参赛者了解具体开赛时刻。 对于Codeforces上的赛事而言,如果一场名为M1的比赛被计划举行,则它的原始时间一般按照UTC(协调世界时)设定。为了得知该场比赛在UTC+8时区的确切开始时间,可以遵循以下逻辑: - 前往Codeforces官网并定位至对应比赛页面。 - 查看比赛所标注的标准UTC起始时间。 - 将此标准时间加上8小时来获取对应的北京时间(即UTC+8)。 由于目前缺乏具体的官方公告链接或者确切日期作为依据,无法直接给出Codeforces M1比赛于UTC+8下的实际发生时段。建议定期访问Codeforces平台查看最新动态更新以及确认最终版程表信息。 ```python from datetime import timedelta, datetime def convert_utc_to_bj(utc_time_str): utc_format = "%Y-%m-%dT%H:%M:%SZ" bj_offset = timedelta(hours=8) try: # 解析UTC时间为datetime对象 utc_datetime = datetime.strptime(utc_time_str, utc_format) # 转换为北京时区时间 beijing_time = utc_datetime + bj_offset return beijing_time.strftime("%Y-%m-%d %H:%M:%S") except ValueError as e: return f"错误:{e}" # 示例输入假设某场Codeforces比赛定于特定UTC时间 example_utc_start = "2024-12-05T17:35:00Z" converted_time = convert_utc_to_bj(example_utc_start) print(f"Codeforces比赛在北京时间下将是:{converted_time}") ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值