题目原文
Farmer John's hobby of conducting high-energy physics experiments on weekends has backfired, causing N wormholes (2 <= N <= 12, N even) to materialize on his farm, each located at a distinct point on the 2D map of his farm (the x,y coordinates are both integers).
According to his calculations, Farmer John knows that his wormholes will form N/2 connected pairs. For example, if wormholes A and B are connected as a pair, then any object entering wormhole A will exit wormhole B moving in the same direction, and any object entering wormhole B will similarly exit from wormhole A moving in the same direction. This can have rather unpleasant consequences.
For example, suppose there are two paired wormholes A at (1,1) and B at (3,1), and that Bessie the cow starts from position (2,1) moving in the +x direction. Bessie will enter wormhole B [at (3,1)], exit from A [at (1,1)], then enter B again, and so on, getting trapped in an infinite cycle!
| . . . . | A > B . Bessie will travel to B then + . . . . A then across to B again
Farmer John knows the exact location of each wormhole on his farm. He knows that Bessie the cow always walks in the +x direction, although he does not remember where Bessie is currently located.
Please help Farmer John count the number of distinct pairings of the wormholes such that Bessie could possibly get trapped in an infinite cycle if she starts from an unlucky position. FJ doesn't know which wormhole pairs with any other wormhole, so find all the possibilities.
PROGRAM NAME: wormhole
INPUT FORMAT:
Line 1: | The number of wormholes, N. |
Lines 2..1+N: | Each line contains two space-separated integers describing the (x,y) coordinates of a single wormhole. Each coordinate is in the range 0..1,000,000,000. |
SAMPLE INPUT (file wormhole.in): 4
0 0
1 0
1 1
0 1
INPUT DETAILS:
There are 4 wormholes, forming the corners of a square.
OUTPUT FORMAT:
Line 1: | The number of distinct pairings of wormholes such that Bessie could conceivably get stuck in a cycle walking from some starting point in the +x direction. |
SAMPLE OUTPUT (file wormhole.out):
2
OUTPUT DETAILS:
If we number the wormholes 1..4 as we read them from the input, then if wormhole 1 pairs with wormhole 2 and wormhole 3 pairs with wormhole 4, Bessie can get stuck if she starts anywhere between (0,0) and (1,0) or between (0,1) and (1,1).
| . . . . 4 3 . . . Bessie will travel to B then 1-2-.-.-. A then across to B again
Similarly, with the same starting points, Bessie can get stuck in a cycle if the pairings are 1-3 and 2-4 (if Bessie enters WH#3 and comes out at WH#1, she then walks to WH#2 which transports here to WH#4 which directs her towards WH#3 again for a cycle).
Only the pairings 1-4 and 2-3 allow Bessie to walk in the +x direction from any point in the 2D plane with no danger of cycling.
分析
| . . . . 4 3 . . . 1-2-.-.-.假设1和2是一对(一对表示假设到达1,就跳到2,假设到达2,就跳到1),4和3是另一对,那么从1出发向正右方运动,则会出现1-2-1-2-1-2无限循环的情况,从4出发往右运动则会出现4-3-4-3-4-3无限循环,要求在给定数据中找出所有的会产生无限循环的组合。
提交代码
/*
ID:
PROG: wormhole
LANG: C++
*/
#include <fstream>
#include <vector>
#include <iostream>
using namespace std;
bool isLoop(int N,const vector<int> &pair, const vector<int> &next)
{
for (int i=0; i!=N;i++)
{
int temp = i;
for (int j=0;j!=N;j++)
{
temp = next[pair[temp]];
if(temp == -1)
break;
}
if(temp != -1)
return true;
}
return false;
}
int GeneratePair(int N, vector<int> &pair, const vector<int> &next)
{
int count = 0;
int i=0;
for (i=0;i!=N;i++)
{
if(pair[i] == -1)
break;
}
if(i == N)
{
if(isLoop(N,pair,next))
return 1;
else
return 0;
}
for (int j=i+1;j!=N;j++)
{
if(pair[j] == -1)
{
pair[i] = j;
pair[j] = i;
count += GeneratePair(N,pair,next);
pair[i] = -1;
pair[j] = -1;
}
}
return count;
}
int main()
{
ifstream fin("wormhole.in");
ofstream fout("wormhole.out");
int N;
fin >> N;
vector<vector<int> > pos(N);
for (int i = 0;i!=N;i++)
{
pos[i].resize(2);
fin >> pos[i][0] >> pos[i][1];
}
vector<int> next_pos(N,-1);
for (int i = 0; i != N ;i++)
{
for (int j=0;j!=N;j++)
{
if(pos[j][1] == pos[i][1] && pos[j][0] > pos[i][0])
if(next_pos[i] == -1 || pos[j][0] - pos[i][0] < pos[next_pos[i]][0] - pos[i][0])
next_pos[i] = j;
}
}
vector<int> pair(N,-1);
int count = GeneratePair(N,pair,next_pos);
fout << count <<endl;
//cout << count << endl;
return 0;
}
提交结果
TASK: wormhole LANG: C++ Compiling... Compile: OK Executing... Test 1: TEST OK [0.016 secs, 3500 KB] Test 2: TEST OK [0.005 secs, 3500 KB] Test 3: TEST OK [0.008 secs, 3500 KB] Test 4: TEST OK [0.005 secs, 3500 KB] Test 5: TEST OK [0.008 secs, 3500 KB] Test 6: TEST OK [0.005 secs, 3500 KB] Test 7: TEST OK [0.008 secs, 3500 KB] Test 8: TEST OK [0.019 secs, 3500 KB] Test 9: TEST OK [0.011 secs, 3500 KB] Test 10: TEST OK [0.019 secs, 3500 KB] All tests OK.
官方参考答案
#include <iostream>
#include <fstream>
using namespace std;
#define MAX_N 12
int N, X[MAX_N+1], Y[MAX_N+1];
int partner[MAX_N+1];
int next_on_right[MAX_N+1];
bool cycle_exists(void)
{
for (int start=1; start<=N; start++) {
// does there exist a cylce starting from start
int pos = start;
for (int count=0; count<N; count++)
pos = next_on_right[partner[pos]];
if (pos != 0) return true;
}
return false;
}
// count all solutions
int solve(void)
{
// find first unpaired wormhole
int i, total=0;
for (i=1; i<=N; i++)
if (partner[i] == 0) break;
// everyone paired?
if (i > N) {
if (cycle_exists()) return 1;
else return 0;
}
// try pairing i with all possible other wormholes j
for (int j=i+1; j<=N; j++)
if (partner[j] == 0) {
// try pairing i & j, let recursion continue to
// generate the rest of the solution
partner[i] = j;
partner[j] = i;
total += solve();
partner[i] = partner[j] = 0;
}
return total;
}
int main(void)
{
ifstream fin("wormhole.in");
fin >> N;
for (int i=1; i<=N; i++) fin >> X[i] >> Y[i];
fin.close();
for (int i=1; i<=N; i++) // set next_on_right[i]...
for (int j=1; j<=N; j++)
if (X[j] > X[i] && Y[i] == Y[j]) // j right of i...
if (next_on_right[i] == 0 ||
X[j]-X[i] < X[next_on_right[i]]-X[i])
next_on_right[i] = j;
ofstream fout("wormhole.out");
fout << solve() << "\n";
fout.close();
return 0;
}