邮票面值设计

来源:互联网 发布:礼券提货系统源码 php 编辑:程序博客网 时间:2024/04/29 03:00

http://www.rqnoj.cn/problem/112

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

  INPUT       N=3   k=2     OUTPUT     1     3     MAX=7   

思路:本题用的是搜索加动态规划剪枝,唉可惜测试的时候没写出来啊 ,搜索还是太弱了,,,

#include <cstdio>#include <cstring>#include <iostream>using namespace std;/int n, m;int dp[10005];   //凑齐 i 面值最少需要多少邮票int sta[25];  //搜索过程中的解int res[25], resl; //最后的解int Dp(int top)  //完全背包{    memset(dp, 0, sizeof(dp));    for(int i = 1; i < 10000; i++){        dp[i] = 10000;        for(int k = 0; k < top; k++){            if(i >= sta[k] && dp[i] > dp[i - sta[k]] + 1){ //状态转移                dp[i] = dp[i - sta[k]] + 1;            }        }        if(dp[i] > n){            return i - 1;        }    }    return -1;}int Dfs(int pos){    int maxn = Dp(pos);  // 计算连续的最大邮资    if(pos == m){        if(maxn > resl){            for(int i = 0; i < m; i++){                res[i] = sta[i];            }            resl = maxn;        }        return 0;    }    for(int i = maxn + 1; i > sta[pos - 1]; i--){  //从连续最大邮资往回搜索        sta[pos] = i;        Dfs(pos + 1);    }    return 0;}int main(){    while(~scanf("%d%d", &n, &m)){        resl = 0;        sta[0] = 1;        Dfs(1);        for(int i = 0; i < m; i++){            printf(i == 0 ? "%d" : " %d", res[i]);        }        printf("\nMAX=%d\n", resl);    }    return 0;}
0 0
原创粉丝点击