APIO 2013 T1 ROBOTS

每个机器人只能和相邻的机器人合并,转成人话就是任何的合并机器人只能是一段区间。而且机器人之间的行动互不干扰。

那么就是区间 \(dp\) 了。设 \(dp_{l,r,x,y}\) 表示令由 \([l,r]\) 的机器人合并成的机器人处在 \((x,y)\),推动 \([l,r]\) 内的机器人行进的最小次数。

转移的时候,我们对每个 \([l,r]\) 枚举它是由哪两块机器人合并起来的,也就是 \([l,mid]\)\((mid,r]\)。然后它在哪里出现,也就是 \((x,y)\),就是 \(dp_{l,mid,x,y}\)\(dp_{mid+1,r,x,y}\) 的和,这是第一步,计算机器人第一次出现的位置的答案。

首先,我们必须在预处理 \(to_{x,y,dir}\) 表示在格子 \((x,y)\) 朝着方向 \(dir\) 推动之后会到达的坐标。这个可以用记忆化搜索来完成,因为 \((x,y,dir)\) 前进一次之后会有唯一确定的新的 \((nx,ny,ndir)\),如果新的位置是障碍,就直接找到答案,否则 \(to_{x,y,dir}=to_{nx,ny,ndir}\)。复杂度是 \(O(hw)\) 的。对所有机器人通用。

然后我们考虑计算推动 \([l,r]\) 到达所有可能到达的位置的答案。第一个想法是 \(\text{Dijkstra}\),但是带 $\log $ 的话,复杂度就有点寄。那怎么办呢?看起来我们的图还挺特殊的(一个路径上的所有点都往某个点连边),难道用 \(\text{SPFA}\) 吗?

这份代码 告诉我们 \(\text{SPFA}\) 在特殊图上的效果确实不错,但是这样做就是没有发现一个特殊性质。

\(dp_{l,r,x,y}\) 的值不会超过 \(hw\)。因为一次推动的结束点最多只有这么多个!那么我们为什么还需要用堆优化 \(\text{Dijkstra}\) 呢?我们可以直接计数排序!我们对所有 \(dp_{l,r,x,y}\) 的值进行计数,然后顺着扫描。因为从当前拓展出的答案只会比更新的点更大,比被更新的原值更小,所以我们可以给每个点维护 \(del\),一旦出队则 \(del\)\(1\),然后就可以进行更新,更新不需要在原位置删除,因为新的位置一定更先出队。

这样,我们就优化了这一过程的答案。不过我们的复杂度是 \(O(n^3hw)\) 的,瓶颈来自第一步枚举初始位置(但是区间 \(dp\) 的常数很小)。

这样我们就得到 \(O(n^3hw)\) 的做法,卡卡常就能通过了。

坑点:在 \(Hack\) 数据中,有可能有走不出去的环。就要在记忆搜索 \(to\) 的过程中记录当前的节点是否 \(inqueue\),如果搜索到有环,那么来的路上的所有的都是绝对不能选的。

int dx[4]={1,0,-1,0},dy[4]={0,-1,0,1};
int dp[10][10][505][505],n,w,h;
int a[505][505],cur[505][505];
int trn[505][505],inq[505][505][4];
int tox[505][505][4],toy[505][505][4],del[505][505];
vt<pii>ope[2000005];
st s;
inline void extend(){
	rep(i,0,8*w*h)ope[i].clear();
	rp(i,w)rp(j,h)del[i][j]=0;
	rp(i,w)rp(j,h)if(a[i][j]&&cur[i][j]!=1e9)ope[cur[i][j]].pb({i,j}),del[i][j]=0;
	rep(d,0,8*w*h){
		for(auto p:ope[d]){
			int x=p.first,y=p.second;
			if(del[x][y])continue;
			del[x][y]=1;
			rd(dir,4){
				int nx=tox[x][y][dir],ny=toy[x][y][dir];
				if(nx==-1)continue;
				if(cur[nx][ny]>d+1){
					cur[nx][ny]=d+1;
					ope[d+1].pb({nx,ny});
				}
			}
		}
	}
}
inline void dfs(int x,int y,int dir){
	if(tox[x][y][dir])return;
	int nx=x+dx[dir],ny=y+dy[dir],ndir=dir;
	if(!a[nx][ny]){
		tox[x][y][dir]=x;
		toy[x][y][dir]=y;
		return;
	}
	ndir=(ndir+trn[nx][ny]+4)%4;
	if(inq[nx][ny][ndir]){
		tox[x][y][dir]=-1;
		return;
	}
	inq[x][y][dir]=1;
	dfs(nx,ny,ndir);
	inq[x][y][dir]=0;
	tox[x][y][dir]=tox[nx][ny][ndir];
	toy[x][y][dir]=toy[nx][ny][ndir];
}
signed main(){
	ios::sync_with_stdio(false);
	cin.tie(0);
	cin>>n>>h>>w;
	rep(i,1,n)rep(j,1,n)rep(x,1,w)rep(y,1,h)dp[i][j][x][y]=1e9;
	rp(i,w){
		cin>>s;
		rp(j,h){
			if(s[j-1]!='x')a[i][j]=1;
			if(s[j-1]=='A')trn[i][j]=-1;
			if(s[j-1]=='C')trn[i][j]=1;
			if(isdigit(s[j-1])){
				int x=s[j-1]-'0';
				dp[x][x][i][j]=0;
			}
		}
	}
	rp(i,w)rp(j,h)if(a[i][j])rd(dir,4)if(!tox[i][j][dir])dfs(i,j,dir);
	rep(len,1,n)rep(l,1,n-len+1){
		int r=l+len-1;
		if(len>1){
			rep(mid,l,r-1){
				rp(i,w)rp(j,h)if(dp[l][mid][i][j]!=1e9&&dp[mid+1][r][i][j]!=1e9){
					dp[l][r][i][j]=min((int)dp[l][r][i][j],dp[l][mid][i][j]+dp[mid+1][r][i][j]);
				}
			}
		}
		rp(i,w)rp(j,h)cur[i][j]=dp[l][r][i][j];
		extend();
		rp(i,w)rp(j,h)dp[l][r][i][j]=cur[i][j];
	}
	int ans=1e9;
	rp(i,w)rp(j,h)ans=min(ans,(int)dp[1][n][i][j]);
	if(ans==1e9)cout<<-1<<endl;
	else cout<<ans<<endl;
	return 0;
}
//Crayan_r
posted @ 2023-03-06 12:01  jucason_xu  阅读(14)  评论(0编辑  收藏  举报