USACO Section 1.3 Wormholes

来源:互联网 发布:windows无法访问xp 编辑:程序博客网 时间:2024/06/10 12:50

题目原文

Wormholes

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):
40 01 01 10 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. 



分析

题目的意思有点绕,输入的数据为给定的几个坐标,例如(0,0),(1,0),(1,1),(0,1),按顺序标在下图中
   | . . . .   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无限循环,要求在给定数据中找出所有的会产生无限循环的组合。
例如输入的数据共有4个点,两两组合总共有3种情况,其中1和2一对、3和4一对,1和3一对、4和2一对都会出现无线循环,1和4一队、2和3一队则不会出现无线循环,因此答案为2。

根据上述分析,求解本题主要需要解决的问题有两个,一个是给出输入两两组合的所有情况,这个如果按排列组合的方法算的话复杂度是很高的,不过题目限制了输入的坐标个数不会超过12个,所以直接遍历所有的情况是可行的;另一个就是在得到某一种组合情况的时候,判断这种情况下会不会出现死循环。


提交代码

 /* 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;elsereturn 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: wormholeLANG: C++Compiling...Compile: OKExecuting...   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 12int 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 solutionsint 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;}

THE END


0 0