USACO Wormholes 解题报告

新加的USACO题都有youtube讲解,感觉非常好。由于section的位置和数据的规模(~12),可以知道就用直观的想法写就可以。即产生所有的pair,每产生一个就看下是否有环。标准程序在检测是否有环部分非常简洁,3,4行代码就搞定了。我这里面又用了一次递归。当然,他这里也是利用了数据规模很小的特点。用递归判断是否有环需要注意的地方(也是我第一次提交挂的原因)是,需要看next的时候(即往右边走的时候)遇到的洞是否之前进去过了,而不应该看从“隧道”到达的点是否经过了。即只考虑地上的情况。因为有种情况是一个点地上遇到一次(通过向右走),后来通过“隧道”到达一次,但之后向右走到头了。就不会陷入题中要求的“无限循环”中。

/* 
ID: thestor1 
LANG: C++ 
TASK: wormhole 
*/
#include <iostream>
#include <fstream>  
#include <cmath>  
#include <cstdio>  
#include <cstring>  
#include <climits>  
#include <cassert>  
#include <string>  
#include <vector>  
#include <set>
#include <map>  
#include <queue>  
#include <stack>  
#include <algorithm>

using namespace std;

bool checkpair(const vector<int> &pairs, int cur, const int N, std::vector<bool> &visited, const vector<int> &next)
{
	// cout<<"[debug]cur: "<<cur<<", next[cur]: "<<next[cur]<<endl;
	// cout<<"[debug][checkpair]next: ";
	// for (int i = 0; i < N; ++i)
	// {
	// 	cout<<i<<": "<<next[i]<<";  ";
	// }
	// cout<<endl;

	// visited[cur] = true;
	if (next[cur] < 0)
	{
		return false;
	}
	if (visited[next[cur]])
	{
		return true;
	}
	visited[next[cur]] = true;
	cur = pairs[next[cur]];
	// if (visited[cur])
	// {
		// return true;
	// }
	// visited[cur] = true;
	return checkpair(pairs, cur, N, visited, next);
}

bool checkpair(const vector<int> &pairs, const vector<int> &next, const int N)
{
	std::vector<bool> visited(N, false);
	for (int i = 0; i < N; ++i)
	{
		for (int k = 0; k < N; ++k)
		{
			visited[k] = false;
		}
		
		if (checkpair(pairs, i, N, visited, next))
		{
			return true;
		}
	}
	return false;
}

void formpair(vector<int> &pairs, vector<bool> &paired, int cur, const vector<int> &next, const int N, int &cnt)
{
	if (cur == N)
	{
		// cout<<"[debug]pairs: ";
		// for (int i = 0; i < pairs.size(); ++i)
		// {
		// 	cout<<pairs[i]<<" ";
		// }
		// cout<<endl;

		if (checkpair(pairs, next, N))
		{
			cnt += 1;
		}
		return;
	}

	if (paired[cur])
	{
		formpair(pairs, paired, cur + 1, next, N, cnt);
	}
	else
	{
		paired[cur] = true;
		for (int i = cur + 1; i < N; ++i)
		{
			if (!paired[i])
			{
				pairs[cur] = i;
				pairs[i] = cur;
				paired[i] = true;
				formpair(pairs, paired, cur + 1, next, N, cnt);
				paired[i] = false;
			}
		}
		paired[cur] = false;
	}
}

int main()
{
	ifstream fin("wormhole.in");
	ofstream fout("wormhole.out");

	int N;
	fin>>N;
	vector<pair<int, int> > wormholes(N);
	for (int i = 0; i < N; ++i)
	{
		int x, y;
		fin>>x>>y;
		wormholes[i] = make_pair(x, y);
	}

	vector<int> next(N, -1);
	for (int i = 0; i < N; ++i)
	{
		int n = -1;
		for (int j = 0; j < N; ++j)
		{
			if (wormholes[j].second == wormholes[i].second && wormholes[j].first > wormholes[i].first)
			{
				if (n < 0 || wormholes[j].first < wormholes[n].first)
				{
					n = j;
				}
			}
		}
		next[i] = n;
	}

	// cout<<"[debug]next: ";
	// for (int i = 0; i < N; ++i)
	// {
	// 	cout<<i<<": "<<next[i]<<";  ";
	// }
	// cout<<endl;

	vector<int> pairs(N);
	vector<bool> paired(N, false);
	int cnt = 0;
	formpair(pairs, paired, 0, next, N, cnt);
	fout<<cnt<<endl;
	fin.close();
	fout.close();
	return 0;  
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值