USACO Combination Lock 解题报告

新加的一道题,标准答案为把所有的数都试一遍。我的解法是把所有的可能性都加到一个set里面,这样避免了两个key允许的数重叠的情况,是一种偷懒的做法。

/* 
ID: thestor1 
LANG: C++ 
TASK: combo 
*/
#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;

set<int> adjs(int d, int N)
{
	std::set<int> fours;
	fours.insert(d);
	fours.insert((d - 1 + N - 1) % N + 1);
	fours.insert((d - 1 + N - 2) % N + 1);
	fours.insert((d - 1 + N + 1) % N + 1);
	fours.insert((d - 1 + N + 2) % N + 1);
	return fours;
}

int tohash(int d1, int d2, int d3, int N)
{
	return d1 * (N + 1) * (N + 1) + d2 * (N + 1) + d3;
}

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

	int N;
	fin>>N;

	std::vector<vector<int> > keys(2, std::vector<int>(3, 0));
	for (int i = 0; i < 2; ++i)
	{
		for (int j = 0; j < 3; ++j)
		{
			int dial;
			fin>>dial;
			keys[i][j] = dial;
		}
	}

	// for (int i = 0; i < 2; ++i)
	// {
	// 	cout<<"key "<<i<<":";
	// 	for (int j = 0; j < 3; ++j)
	// 	{
	// 		cout<<keys[i][j]<<"\t";
	// 	}
	// 	cout<<endl;
	// }

	set<int> validkeys;
	for (int k = 0; k < 2; ++k)
	{
		set<int> firstadjs = adjs(keys[k][0], N);
		set<int> secondadjs = adjs(keys[k][1], N);
		set<int> thirdadjs = adjs(keys[k][2], N);
		
		for (set<int>::iterator iter1 = firstadjs.begin(); iter1 != firstadjs.end(); ++iter1)
		{
			for (set<int>::iterator iter2 = secondadjs.begin(); iter2 != secondadjs.end(); ++iter2)
			{
				for (set<int>::iterator iter3 = thirdadjs.begin(); iter3 != thirdadjs.end(); ++iter3)
				{
					// cout<<*iter1<<", "<<*iter2<<", "<<*iter3<<endl;
					int h = tohash(*iter1, *iter2, *iter3, N);
					validkeys.insert(h);
				}
			}
		}
	}

	fout<<validkeys.size()<<endl;

	fin.close();
	fout.close();
	return 0;  
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值