[题解] [JSOI2010] 找零钱的洁癖

题面

题解

说实话, 其实我也不知道这题正解是啥
你看着数据范围不像爆搜题
但是爆搜他就是可以过, 我也不知道为啥
奇葩

Code

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

int X, a[1005], cnt, q[1000005], num[1000005]; 
map<int, bool> mp; 

template < typename T >
inline T read()
{
	T x = 0, w = 1; char c = getchar();
	while(c < '0' || c > '9') { if(c == '-') w = -1; c = getchar(); }
	while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
	return x * w; 
}

int greedy()
{
	int res = 0, sum = X;
	for(int i = cnt; i; i--)
	{
		res += sum / a[i];
		sum -= sum / a[i] * a[i]; 
	}
	return sum ? 0x3f3f3f3f : res; 
}

int bfs()
{
	int l = 1, r = 0;
	q[++r] = 0, num[r] = 0; 
	while(l <= r && r <= 1000000)
	{
		for(int i = 1; i <= cnt; i++)
		{
			q[++r] = q[l] + 1, num[r] = num[l] > X ? num[l] - a[i] : num[l] + a[i]; 
			if(num[r] == X) return q[r]; 
			if(mp[num[r]] == 1) { r--; continue; }
			mp[num[r]] = 1; 
		}
		l++; 
	}
	return 0x3f3f3f3f; 
}

int main()
{
	X = read <int> ();
	while(scanf("%d", &a[++cnt]) != EOF);
	cnt--; sort(a + 1, a + cnt + 1); 
	if(!X) puts("0");
	else printf("%d\n", min(greedy(), bfs())); 
	return 0; 
}
posted @ 2020-02-04 10:07  ztlztl  阅读(104)  评论(0编辑  收藏  举报