CF29E Quarrel 题解

我们可以另 \(f_{u,v,t}\) 为 A 在 \(u\),B 在 \(v\) ,并且当前轮到第 \(t\) 个人(\(0\) 代表 A,\(1\) 代表 B)移动是的最小步数。

那么就可以使用 BFS 来挨个进行松弛,松弛的时候记录前驱。

注意:在移动 B 的时候,要注意 B 的目的地不能是 A 当前在的位置。

核心代码:

int f[505][505][2],vis[505][505][2],pre[505][505][2][2];
struct node
{
	int u;
	int v;
	int p;
};
int head[505],to[20005],nxt[20005],tot=0;
void add(int u,int v)
{
	nxt[++tot]=head[u];
	head[u]=tot;
	to[tot]=v;
}
void bfs(int n)
{
	queue<node> q;
	memset(f,63,sizeof f);
	q.push((node){1,n,0});f[1][n][0]=0;
	while(!q.empty())
	{
		int u=q.front().u,v=q.front().v,p=q.front().p;q.pop();
		vis[u][v][p]=0;
		if(!p)
		{
			for(register int i=head[u];i;i=nxt[i])
			{
            	//这里不用判断是否相等,因为此时只有A走了,B还没走
				if(f[to[i]][v][1]>f[u][v][0]+1)//松弛
				{
					f[to[i]][v][1]=f[u][v][0]+1;
					pre[to[i]][v][1][0]=u;
					pre[to[i]][v][1][1]=v;
                    //记录前驱
					if(!vis[to[i]][v][1])
					{
						q.push((node){to[i],v,1});
						vis[to[i]][v][1]=1;
					}
				}
			}
		}
		else
		{
			for(register int i=head[v];i;i=nxt[i])
			{
				if(to[i]==u)continue;
				if(f[u][to[i]][0]>f[u][v][1])
				{
					f[u][to[i]][0]=f[u][v][1];
					pre[u][to[i]][0][0]=u;
					pre[u][to[i]][0][1]=v;
					if(!vis[u][to[i]][0])
					{
						q.push((node){u,to[i],0});
						vis[u][to[i]][0]=1;
					}
				}
			}
		}
	}
}
posted @ 2020-10-31 09:49  ฅ(OωO)ฅ  阅读(91)  评论(0)    收藏  举报
"scale": 1 }, "display": { "position": "left", "width": 100, "height": 200, "hOffset": 70, "vOffset": 0 }, "mobile": { "show": true, "scale": 0.5 }, "react": { "opacityDefault": 0.7, "opacityOnHover": 0.2 } }); window.onload = function(){ $("#live2dcanvas").attr("style","position: fixed; opacity: 0.7; left: 70px; bottom: 0px; z-index: 1; pointer-events: none;") } -->