USACO 1.4 Wormholes 蟲洞

DWAE86發表於2018-07-25

題目描述


農夫約翰愛好在週末進行高能物理實驗的結果卻適得其反,導致N個蟲洞在農場上(2<=N<=12,n是偶數),每個在農場二維地圖的一個不同點。

根據他的計算,約翰知道他的蟲洞將形成 N/2 連線配對。例如,如果A和B的蟲洞連線成一對,進入蟲洞A的任何物件體將從蟲洞B出去,朝著同一個方向,而且進入蟲洞B的任何物件將同樣從蟲洞A出去,朝著相同的方向前進。這可能發生相當令人不快的後果。

例如,假設有兩個成對的蟲洞A(1,1) 和 B(3,1),貝茜從(2,1)開始朝著 +x 方向(右)的位置移動。貝茜將進入蟲洞 B(在(3,1)),從A出去(在(1,1)),然後再次進入B,困在一個無限迴圈中!

| . . . .
| A > B .      貝茜會穿過B,A,
+ . . . .      然後再次穿過B

 農夫約翰知道他的農場裡每個蟲洞的確切位置。他知道貝茜總是向 +x 方向走進來,雖然他不記得貝茜的當前位置。請幫助農夫約翰計算不同的蟲洞配對(情況),使貝茜可能被困在一個無限迴圈中,如果她從不幸的位置開始。

 

樣例輸入&輸出


 sample input

4
0 0
1 0
1 1
0 1

 sample output

2

 

分析&反思


 dfs + 模擬檢驗,都有需要提高的地方

剛開始想到了一個簡單剪枝,想到了dfs配對,想到了向大配對去重, 想到了從蟲洞出發檢查。

想不到dfs的程式碼實現,想不到partner陣列 ,想不到right陣列記錄右邊的點直接跳

 

dfs很久沒寫了,基本的幾點:

1. 終點狀態,ans++,return ans。

2. 退出後partner還原為零

 

ps:right是一個string類的函式,屬於關鍵字, 不可用於命名。補充:

CString a,b;
 a = "123456789";


 b = a.Left(4);   //值為:1234
 b = a.Mid(3);    //值為:456789
 b = a.Mid(2, 4); //值為:3456       //4為長度 
 b = a.Right(4);  //值為:6789

 

程式碼


 

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

int n;
int x[20], y[20], partner[20], right1[20];

int check() {
	int pos, start;
	for(int i = 1; i <= n; i++) {
		pos = start = i;
		for(int cnt = 0; cnt < n; cnt++) {
			pos = partner[right1[pos]];
			if(pos == start) return 1;
			if(!pos) break;
		}
	}
	return 0;
}

int solve () {
	int i ,j, ans = 0;    //int ans = 0
	for(i = 1; i <= n; i++) if(!partner[i]) break;
	
	if(i == n+1) 
		if(check()) return ++ans;  // i在最後一個迴圈變成n+1,終點狀態 
	
	// 向大的匹配,去重,想到了,如同分蘋果,dfs常用去重 
	for(j = i+1; j <= n; j++) 
	if(!partner[j]) {
		partner[i] = j;
		partner[j] = i;
		ans += solve();    // +=!!!
		partner[i] = partner[j] = 0;
	}  
	return ans;
}

int main () {

	freopen("wormhole.in", "r", stdin);
	freopen("wormhole.out", "w", stdout); 

	cin >> n;
	for(int i = 1; i <= n; i++) cin >> x[i] >> y[i];
				
	//  記錄每個點右邊的點,直接跳; 
	for(int i = 1; i <= n; i++)
	for(int j = 1; j <= n; j++) 
		if(y[i] == y[j] && x[i] < x[j]) // 必須j在i的右邊,順便去掉ij相同的情況 
			if(!right1[i] || x[right1[i]]-x[i] > x[j]-x[i]) right1[i] = j;
	
	cout << solve() << endl;
	
	return 0;
	
}

備註


solve () 裡的 i 用的很巧妙。

很多還要重新pick up啊!

相關文章