題解 noip2013 華容道

2021-09-29 08:41:44 字數 3413 閱讀 4110

題目鏈結

除去多次詢問不談,這道題大致的框架是非常明顯的搜尋。但是雖然是多次詢問,棋盤的狀態是不會變的,並且只有部分的位置是真正有價值的。那麼就可以考慮圖論建模,在這些有價值的狀態上跑從終態到末態的最短路。因為棋子要移動的時候,空白塊一定要移到它的周圍,所以我們可以為這種周圍的位置編號。f[x

][y]

[i

]f[x][y][i]

f[x][y

][i]

表示在點(x,

y)

(x, y)

(x,y

)的方向i(0

≤i≤3

)i(0\le i \le 3)

i(0≤i≤

3)上的位置的編號。這裡我們有兩個陣列表示方向的偏移量,不同的i

ii分別配對左、右、上、下:dx[

4]=0

,0,−

1,1,

dy[4

]=−1

,1,0

,0

dx[4]=,dy[4]=

dx[4]=

0,0,

−1,1

,dy[

4]=−

1,1,

0,0。這樣編號的好處是,ixo

r1

i \ xor\ 1

ixor

1即可表示相反的方向

點建好了,接下來考慮怎麼連邊。顯然的一點是,為了使目標棋子更快地前進,空白格移動到棋子旁的路上不應該與棋子發生交換。對於乙個在棋子旁邊的空白格,它有以下的選擇:

繞到棋子的另乙個方向上,使得棋子向該方向前進,即:$f[x][y][i]\to f[x][y][j](i\not= j) $

直接和棋子交換位置,讓棋子向原本的空白格的方向前進,即:f[x

][y]

[i]→

f[x+

dx[i

]][y

+dy[

i]][

ixor

1]

f[x][y][i]\to f[x+dx[i]][y+dy[i]][i \ xor \ 1]

f[x][y

][i]

→f[x

+dx[

i]][

y+dy

[i]]

[ixo

r1]由於第一種選擇不能受到各種元素限制,所以需要bfs來確定邊權。作完這些預處理之後,這些點之間就構成了乙個圖論模型。對於每次詢問,對移動的棋子周圍的4個位置做一次bfs,得到讓空白格(在不移動該棋子的情況下)移動到棋子四周的最小代價。再把這四個初狀態壓入佇列中,跑一遍spf

aspfa

spfa

,最後列舉末狀態取乙個dis

disdi

s的mi

nmin

min就是答案了

還有一些細節:

起點和終點相同時記得特判

正確估計模型中最多會有多少個點來開陣列

具體請結合**理解:

//從main開始看

#include

#include

const

int maxn=50;

const

int maxm=

1000000

;const

int inf=

0x3f3f3f3f

;int a[maxn]

[maxn]

,f[maxn]

[maxn][4

];int dx[4]

=,dy[4]

=;int head[maxn*maxn*4]

,to[maxm]

,nxt[maxm]

,val[maxm]

;int dis[maxn*maxn]

;int cnt,tot;

int n,m,q;

bool vis[maxn]

[maxn]

,inq[maxn*maxn]

;struct node

node

(int a,

int b,

int c)};

struct queue

void

push

(node x)

void

pop(

) node front()

bool

empty()

};//這兩個手寫佇列分別給bfs和spfa用= =,直接用stl也差不多的

struct que

void

push

(int x)

void

pop(

)int

front()

bool

empty()

};intmin

(int x,

int y)

bool

valid

(int x,

int y)

void

add(

int u,

int v,

int w)

intbfs

(int target_x,

int target_y,

int sx,

int sy,

int tx,

int ty)

}return inf;

}int

spfa

(int ex,

int ey,

int sx,

int sy,

int tx,

int ty)

while

(!q.

empty()

)}}int ans=inf;

for(

int i=

0;i<

4;i++

) ans=

min(ans, dis[f[tx]

[ty]

[i]]);

return ans==inf?-1

:ans;

}int

main()

for(

int x=

1;x<=n;x++

)for

(int y=

1;y<=m;y++

)for

(int i=

0;i<

4;i++

)for

(int j=

0;j<

4;j++

)//選擇1

for(

int x=

1;x<=n;x++

)for

(int y=

1;y<=m;y++

)for

(int i=

0;i<

4;i++

)while

(q--

)return0;

}

題解 P1979 華容道 Noip2013

小 b 最近迷上了華容道,可是他總是要花很長的時間才能完成一次。於是,他想到用程式設計來完成華容道 給定一種局面,華容道是否根本就無法完成,如果能完成,最少需要多少時間。小 b 玩的華容道與經典的華容道遊戲略有不同,遊戲規則是這樣的 在乙個 n mn times mn m 棋盤上有 n times ...

NOIP2013 華容道 廣搜 spfa

問題描述 小 b 最近迷上了華容道,可是他總是要花很長的時間才能完成一次。於是,他想到用程式設計來完成華容道 給定一種局面,華容道是否根本就無法完成,如果能完成,最少需要多少時間。小 b 玩的華容道與經典的華容道遊戲略有不同,遊戲規則是這樣的 在乙個 n m 棋盤上有 n m 個格仔,其中有且只有乙...

NOIP2013提高組day2 華容道

給出一張n m的棋盤,有一些點上有障礙物,其他點上都是棋子。給出q次詢問,每次詢問給出乙個空格,乙個目標棋子,乙個目標位置,每一步可以把乙個棋子移進空格,求把目標棋子移動到目標位置的最小步數。n,m 30,q 500 第一眼看到就知道是大暴力題,發現詢問次數少的時候一次bfs就解決了,那麼詢問多起來...