您的位置:首页 > 其它

noip1999 邮箱面值设计

2015-01-08 21:20 218 查看
题意很好理解,看起来要解决也挺简单的。就是直接DFS。这个每个人都知道,不过对于题目中给出的数据范围,我就无语了,于是觉得无从下手。后来就查看高手的博客,得到的答案是出题人在坑我们!好了,把这些忘记吧。重回我们的正题。DFS遍历没问题,我们每次选择k种不同的邮票,然后测试他最多从1能拼凑到多少。这时问题就来了,选择的邮票面值最大多少?我们总不能一直让它DFS下去吧?那咋处理呢?我们假设当前已经用了i种邮票,然后能拼凑到的最大连续值是maxn,那么我们下一种要选择的邮票面值必然不能高于maxn+1,不然maxn+1是无论如何取不到了。因此,这轮遍历我们选择的邮票最大值就是maxn+1了。同时,我们邮票的选取是从小到大这样选过来的,所以这次要选的邮票值肯定要大于前一种邮票的值啦。那么,问题就解决了。(ps:如何测试连续最大值?这是个完全背包问题,我一说你肯定就懂了)。好了,接下来是代码。

#include <iostream>
#include <cstdlib>
using namespace std;
#define maxn 500
#define min(a,b) a<b?a:b
int a[50];
int b[50];
int f[maxn];
int answer,n,m;
void dfs(int step)
{
int v,j,i;
memset(f, 1<<6, sizeof(f));//初始化为一个大值
f[0]=0;
for (v=1; v<=maxn; v++) {
for (j=1; j<=step&&a[j]<=v; j++) {
f[v]=min(f[v], f[v-a[j]]+1);
}//完全背包问题,这里的f[i]代表当前用了i枚邮票
if (f[v]>n) {//多于给出的限制,就只能取到v-1的值了
v--;
if (v>answer) {
answer=v;
for (i=1; i<=step; i++) {
b[i]=a[i];
}
}
break;
}
}
if (step==m) {//邮票种类用完了,返回
return;
}
for (i=v+1; i>a[step]; i--) {//下一种选择的邮票的值的范围
a[step+1]=i;
dfs(step+1);
}
}
int main(int argc, const char * argv[]) {
int i;
while (cin>>n>>m) {
answer=-1;
a[1]=1;
dfs(1);
for (i=1; i<=m; i++) {
cout<<b[i]<<" ";
}
cout<<endl<<"MAX="<<answer<<endl;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: