一名苦逼的OIer,想成为ACMer

Iowa_Battleship

洛谷1021 邮票面值设计

原题链接

爆搜面值,\(DP\)判断就好。
一开始打了记搜,结果连\(5\ 5\)的数据都过不去。。最后还是老老实实写了\(DP\),不过还是跑不过\(7\ 5\)的数据,但因为这题数据极水,所以轻松过了。
我也去网上翻了翻,目前没有发现哪份代码能真正过满数据,所以就懒得改了。反正能\(A\)

#include<cstdio>
#include<cstring>
using namespace std;
const int N = 20;
const int M = 1e3;
int f[M], p[N], an[N], ma, n, k;
inline int minn(int x, int y) { return x < y ? x : y; }
int calc(int nw)
{
	int i, j, m = p[nw] * n;
	memset(f, 60, (m + 1) << 2);
	f[0] = 0;
	for (i = 1; i <= nw; i++)
		for (j = p[i]; j <= m; j++)
			f[j] = minn(f[j], f[j - p[i]] + 1);
	for (i = 1; i <= m; i++)
		if (f[i] > n)
			return i - 1;
	return m;
}
void dfs(int nw, int m)
{
	if (nw > k)
	{
		if (ma < m)
		{
			ma = m;
			for (int i = 1; i <= k; i++)
				an[i] = p[i];
		}
		return;
	}
	for (int i = p[nw - 1] + 1; i <= m + 1; i++)//显然最大只能为最大连续值+1,否则肯定不能拼上,而因为每种邮票无限,所以从前种价格+1开搜
	{
		p[nw] = i;
		dfs(nw + 1, calc(nw));//每次DP出最大连续值
	}
}
int main()
{
	scanf("%d%d", &n, &k);
	p[1] = 1;
	dfs(2, n);
	for (int i = 1; i <= k; i++)
		printf("%d ", an[i]);
	printf("\nMAX=%d", ma);
	return 0;
}

posted on 2018-12-16 21:40  Iowa_Battleship  阅读(166)  评论(0编辑  收藏  举报

导航