[luoguP1021] 邮票面值设计(DFS + dp)

传送门

数据很小,可以DFS,判断的时候用背包DP

然而不知到枚举到哪里。。。。

首先枚举前可以求一遍题目中的MAX,下一层DFS的时候可以只枚举到MAX + 1,因为再往上就必定会出现断层

蒟蒻很菜,人为规定背包上界。。。。

然后可以A

代码

#include <cstdio>
#include <cstring>
#define min(x, y) ((x) < (y) ? (x) : (y))
#define max(x, y) ((x) > (y) ? (x) : (y))

int n, k, ans;
int f[351], a[351], anslist[301];
bool b[106];

inline int check()
{
	int i, j, cnt = 0;
	for(i = 1; i <= 101; i++)
		if(b[i])
			a[++cnt] = i;
	memset(f, 127 / 3, sizeof(f));
	f[0] = 0;
	for(i = 1; i <= k; i++)
		for(j = a[i]; j <= 350; j++)
			f[j] = min(f[j], f[j - a[i]] + 1);
	for(i = 1; i <= 350; i++)
		if(f[i] > n)
		{
			if(ans < i - 1)
			{
				ans = i - 1;
				for(j = 1; j <= k; j++) anslist[j] = a[j];
			}
			break;
		}
	return i - 1;
}

inline void dfs(int p, int j, int up)
{
	if(p > k) return;
	int i, u;
	for(i = j + 1; i <= up + 1; i++)
		if(!b[i])
		{
			b[i] = 1;
			u = check();
			dfs(p + 1, i, u);
			b[i] = 0;
		}
}

int main()
{
	int i;
	scanf("%d %d", &n, &k);
	b[1] = 1;
	dfs(2, 1, n);
	for(i = 1; i <= k; i++) printf("%d ", anslist[i]);
	printf("
MAX=%d
", ans);
	return 0;
}

  

原文地址:https://www.cnblogs.com/zhenghaotian/p/7084120.html