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; }
相关文章推荐
- NOIP 1999 邮票面值设计 解题报告
- 【NOIP1999】邮票面值设计(水题水积分)
- [NOIP1999]邮票面值设计
- 【NOIP1999】邮票面值设计 dfs
- [NOIP1999]邮票面值设计
- noip1999 邮票面值设计 (搜索+完全背包)
- NOIP1999邮票面值设计[搜索|DP]
- [普及]NOIP 1999 邮票面值设计
- 【暴力搜索】【动态规划】[NOIP 1999]邮票面值设计
- NOIP 1999 邮票面值设计 解题报告
- NOIP1999 邮票面值设计
- 【NOIP1999】邮票面值设计
- NOIP 1999 邮票面值设计 搜索与动归
- [NOIP1999]邮票面值设计
- [NOIP1999提高] CODEVS 1047 邮票面值设计(dfs+dp)
- NOIP1999邮票面值设计
- 【NOIP1999】邮票面值设计 dfs+dp
- 1047 邮票面值设计 1999年NOIP全国联赛提高组
- noip 邮票面值设计 - 搜索 - 动态规划
- 【最长上升子序列】[NOIP1999]拦截导弹