1
NPSC2005高中組決賽 / Re: NPSC 2005 高中組 決賽 H.光輪2005
« 於: 四月 04, 2018, 01:36:18 am »
構造一張圖 G = (V, E),其中
值得一提的是,一定存在一條從 (0, n+1) 到某個 (i, i) 的路徑。我們把 G 裡的頂點分成下面這幾種,並討論它們的度數。
以下是我的 C++ code:
- V 裡的任一元素代表兩人的所在位置,以無序對 (i, j) (若 hi = hj),或有序對 (i, j+1/2) (若 min{hj, hj+1} < hi < max{hj, hj+1}) 表示。
- 設 u, v ∈ V。規定 uv ∈ E 若且唯若兩人可以在只上山或下山一次的情況下從 u 到達 v。
值得一提的是,一定存在一條從 (0, n+1) 到某個 (i, i) 的路徑。我們把 G 裡的頂點分成下面這幾種,並討論它們的度數。
- (0, 0), (0, n+1), (n+1, n+1) 的度數都是 1。
- 若 i ≠ 0, n+1 且 hi = 0,則 (0, i) 和 (i, n+1) 的度數都是 2。
- 若 i ≠ 0, n+1,則 (i, i) 的度數是 3。
- 若 i ≠ j 且 hi = hj,則 (i, j) 的度數是 4 (若 i, j 同為山頂或山谷) 或 0 (若 i, j 一者是山頂另一者是山谷)。
- 設 v := (i, j+1/2) 為一合法頂點,則 v 的度數是 2。
以下是我的 C++ code:
代碼: [選擇]
#include<cassert>
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
using namespace std;
#define N 210
typedef pair<int, int> pii;
int n, h[2*N];
vector<int> g[4*N*N];
bool vis[4*N*N];
int state(int i, int j){
if(i > j){
swap(i, j);
}
return i*(2*n+3)+j;
}
int move(int i, int j, int di, int dj){
int c = (i&2)-1;
if(j&1){
if(c*h[i+2*di] < c*h[j+dj]){
return state(i+di, j+dj);
}else if(c*h[i+2*di] == c*h[j+dj]){
return state(i+2*di, j+dj);
}else{
return state(i+2*di, j);
}
}else{
if(c*h[i+2*di] < c*h[j+2*dj]){
return state(i+di, j+2*dj);
}else if(c*h[i+2*di] == c*h[j+2*dj]){
return state(i+2*di, j+2*dj);
}else{
return state(i+2*di, j+dj);
}
}
}
bool meet(int v){
return v/(2*n+3) == v%(2*n+3);
}
int main(){
while(scanf("%d", &n), n){
h[0] = h[2*n+2] = 0;
for(int i=1; i<=n; i++){
scanf("%*d%d", h+2*i);
}
scanf("%*d");
for(int i=0; i<(2*n+3)*(2*n+3); i++){
g[i].clear();
}
g[state(0, 0)].push_back(move(0, 0, 1, 1));
g[state(0, 2*n+2)].push_back(move(0, 2*n+2, 1, -1));
g[state(2*n+2, 2*n+2)].push_back(move(2*n+2, 2*n+2, -1, -1));
for(int j=4; j<=2*n-2; j+=4) if(h[j] == 0){
g[state(0, j)].push_back(move(0, j, 1, -1));
g[state(0, j)].push_back(move(0, j, 1, 1));
g[state(j, 2*n+2)].push_back(move(j, 2*n+2, -1, -1));
g[state(j, 2*n+2)].push_back(move(j, 2*n+2, 1, -1));
}
for(int i=2, c=1; i<=2*n; i+=2, c*=(-1)){
for(int j=i; j<=2*n; j+=4) if(h[i] == h[j]){
g[state(i, j)].push_back(move(i, j, -1, -1));
g[state(i, j)].push_back(move(i, j, -1, 1));
g[state(i, j)].push_back(move(i, j, 1, -1));
g[state(i, j)].push_back(move(i, j, 1, 1));
}
for(int j=1; j<=2*n-1; j+=4) if(h[j-1]<h[i] && h[i]<h[j+1]){
g[state(i, j)].push_back(move(i, j, -1, -c));
g[state(i, j)].push_back(move(i, j, 1, -c));
}
for(int j=3; j<=2*n+1; j+=4) if(h[j-1]>h[i] && h[i]>h[j+1]){
g[state(i, j)].push_back(move(i, j, -1, c));
g[state(i, j)].push_back(move(i, j, 1, c));
}
}
bool sol = false;
memset(vis, false, sizeof(vis));
queue<pii> bfs;
bfs.push(make_pair(0, state(0, 2*n+2)));
vis[state(0, 2*n+2)] = true;
while(!bfs.empty()){
pii p = bfs.front(); bfs.pop();
int d=p.first, v=p.second;
if(meet(v)){
printf("%d\n", d-1);
sol=true; break;
}
for(int i=0; i<(int)g[v].size(); i++) if(!vis[g[v][i]]){
bfs.push(make_pair(d+1, g[v][i]));
vis[g[v][i]] = true;
}
}
assert(sol);
}
return 0;
}