UVA 1601 The Morning after Halloween
阿新 • • 發佈:2019-02-27
front conn pro lap 數量 有一個 需要 fin space
https://vjudge.net/problem/UVA-1601
題目
你在遊樂場的鬼屋裏當操作員,專門控制鬼屋裏的機器人……某日沒事幹的出題人把這些機器人搬到了其他地方,你需要在最短的時間內遙控機器人讓他們回到原位。所有機器人都可以同時在1秒內朝四個方向(上下左右)移動1格,但是每次移動都必須符合以下條件
- 每個格子只能有一個機器人
- 任意兩個機器人的位置不能交換
- 不能移動到墻裏……
問你需要至少多少時間才能把所有機器人歸位。
輸入包含多組數據
地圖的寬、高和機器人的數量
下面幾行表示地圖,其中小寫字母表示機器人的位置,大寫字母表示機器人的終點,‘#‘表示墻,‘ ‘表示可以走的位置……
輸出每組數據下的最短時間
樣例輸入
5 5 2 ##### #A#B# # # #b#a# ##### 16 4 3 ################ ## ########## ## # ABCcba # ################ 0 0 0 ################ ### ## # ## ## # ## # c# # ## ########b# # ## # # # # # # ## # # ## ## a# # # # # ### ## #### ## # ## # # # # # ##### # ## ## #### #B# # # ## C# # ### # # # ####### # # ###### A## # # # ## ################ 0 0 0
樣例輸出
7 36 77
題解
只用了一個單向bfs,對空格編號建圖,用前向星……
檢測能否互換需要分n=2和n=3兩種情況考慮
n=2時很簡單
n=3時要考慮$\binom{3}{2}$種情況,頭暈還多想了3個位置都換了的情況,其實這是不可能的,由於只能移動一步,所以加上這個這只是浪費時間……
AC代碼(1080ms,去掉浪費時間的部分是750ms)
#include<bits/stdc++.h> using namespace std; #define REP(i,x,y) for(register int i=(x); i<(y); i++) #define REPE(i,x,y) for(register int i=(x); i<=(y); i++) #ifdef sahdsg #define DBG(a,...) printf(a, ##__VA_ARGS__) #else #define DBG(a,...) (void)0 #endif #define MAXN 20 #define MAXP 300 int w,h,n; int cnt; int mp[MAXN][MAXN]; int st[3],ed[3]; bool vis[MAXP][MAXP][MAXP]; int hed[131072], nxt[131072], poi[131072], fstar=0; inline void conn(int f, int t) { nxt[fstar]=hed[f]; poi[fstar]=t; hed[f]=fstar++; } struct node { int s; int p[3]; node(int *x, int y=0):s(y) {memcpy(p,x,sizeof p);} }; inline void bfs() { memset(vis,0,sizeof vis); queue<node> q; q.push(node(st)); int ans=-1; while(!q.empty()) { node now = q.front();q.pop(); if(memcmp(now.p,ed,sizeof ed)==0) {ans=now.s; break;} int i[3],k[3],dis[3]; REP(i,0,n) dis[i]=now.p[i]; memset(k,0,sizeof k); #define CHK k[0]!=k[1] && k[1]!=k[2] && k[2]!=k[0] for(i[0]=hed[now.p[0]]; ~i[0]; i[0]=nxt[i[0]]) { k[0]=poi[i[0]]; if(n>=2) for(i[1]=hed[now.p[1]]; ~i[1]; i[1]=nxt[i[1]]) { k[1]=poi[i[1]]; if(n>=3) for(i[2]=hed[now.p[2]]; ~i[2]; i[2]=nxt[i[2]]){ k[2]=poi[i[2]]; if(!vis[k[0]][k[1]][k[2]]) if(CHK) { if(dis[0]==k[1] && dis[1]==k[0]) continue; if(dis[0]==k[2] && dis[2]==k[0]) continue; if(dis[1]==k[2] && dis[2]==k[1]) continue; int j[3],l[3]; memcpy(j,k,sizeof j);memcpy(l,dis,sizeof j); sort(j,j+3);sort(l,l+3); if(memcmp(j,l,sizeof j)==0) continue; vis[k[0]][k[1]][k[2]]=1; q.push(node(k,now.s+1)); } } else if(!vis[k[0]][k[1]][0]) if(k[0]!=k[1]) { if(k[0]==dis[1] && k[1]==dis[0]) continue; vis[k[0]][k[1]][0]=1; q.push(node(k,now.s+1)); } } else if(!vis[k[0]][0][0]){vis[k[0]][0][0]=1; q.push(node(k,now.s+1));} } } printf("%d\n", ans); } int main() { #ifdef sahdsg freopen("in.txt", "r", stdin); #endif while(~scanf("%d%d%d", &w, &h, &n) && w) { cnt=0; memset(hed,-1,sizeof hed); memset(st,0,sizeof st); memset(ed,0,sizeof ed); fstar=0; REP(i,0,h) REP(j,0,w) { char ch = getchar(); if(ch<‘ ‘)ch=getchar(); if(ch==‘#‘) {mp[i][j]=-1; continue;} mp[i][j]=cnt; if(ch>=‘a‘ && ch<=‘z‘) st[ch-‘a‘]=cnt; else if(ch>=‘A‘ && ch<=‘Z‘) ed[ch-‘A‘]=cnt; conn(cnt,cnt); if(i>0 && mp[i-1][j]>=0) conn(mp[i-1][j],cnt),conn(cnt,mp[i-1][j]); if(j>0 && mp[i][j-1]>=0) conn(mp[i][j-1],cnt),conn(cnt,mp[i][j-1]); cnt++; } bfs(); } return 0; }
比較慢,可以用雙向bfs或A*優化……
UVA 1601 The Morning after Halloween