洛谷1021 邮票面值设计

洛谷1021 邮票面值设计

本题地址: http://www.luogu.org/problem/show?pid=1021

题目描述

  给定一个信封,最多只允许粘贴N张邮票,计算在给定K(N+K≤40)种邮票的情况下(假定所有的邮票数量都足够),如何设计邮票的面值,能得到最大值MAX,使在1~MAX之间的每一个邮资值都能得到。
    
  例如,N=3,K=2,如果面值分别为1分、4分,则在1分~6分之间的每一个邮资值都能得到(当然还有8分、9分和12分);如果面值分别为1分、3分,则在1分~7分之间的每一个邮资值都能得到。可以验证当N=3,K=2时,7分就是可以得到的连续的邮资最大值,所以MAX=7,面值分别为1分、3分。

输入输出格式

输入格式:

2个整数,代表N,K。

输出格式:

2行。第一行若干个数字,表示选择的面值,从小到大排序。
第二行,输出“MAX=S”,S表示最大的面值。

输入输出样例

输入样例#1:
3 2
输出样例#1:
1 3
MAX=7

————————————————————————————————————————————————

分析:连续邮资问题,这题数据范围有点怪。。最坏情况显然过不了但还是AC了。
人家总结的很好了。By D_Double
我用搜索+剪枝写法,搜索出now[1..k],表示取这k种面值时能得到最大连续邮资,第i种面值搜索范围最小now[i-1]+1,最大是update(最大连续邮资)+1。
update函数更新用now[1..i]的面值取n个时能得到的最大连续邮资,只要搜索出所有组合就可以了。

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define MAXN 50
int n,k,kind,ans[MAXN],now[MAXN],max,x,maxans=0;
_Bool vis[1000];
void dfs_N(int num,int sum,int prev)
{
	vis[sum]=1;
	if(num==n+1)return;//选完n个邮票
	int i;
	for(i=prev;i<=kind;i++)//下一个邮票
	{
		dfs_N(num+1,sum+now[i],i);
	} 
}
int update(int x)//得到当前邮票种类集合的最大连续值 
{
	memset(vis,0,sizeof(vis));
	dfs_N(1,0,1);
	int i;for(i=1;vis[i+1];i++);
	return i;
}
void dfs_K(int step,int best)//搜索面值种类方案 
{
	if(step==k+1)//选完k种面值
	{
		if(best>maxans)
		{
			maxans=best;
			memcpy(ans,now,sizeof(now));	
		}
		return;	
	} 
	int i;
	for(i=now[step-1]+1;i<=best+1;i++)//下一种面值 
	{
		now[step]=i;
		kind=step;
		dfs_K(step+1,update(best));
	}
}
int main(void)
{
	scanf("%d%d",&n,&k);
	now[1]=1;max=n;
	dfs_K(2,max);
	int i;
	for(i=1;i<=k;i++)printf("%d ",ans[i]);
	printf("\nMAX=%d",maxans);
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值