连续邮资问题

#include <iostream>
#include <cstring>
#define INF 0x7fffffff
using namespace std;
//蓝桥杯 ADV-6
//算法书上有
int a[20],n,k,MAX=0,best[20],y[10001];
//n张邮票,k种
//如何求具体的邮资区间?方法是求出y【k】=m,代表达到k的邮资最少需要m张票。
//然后顺序查看最大的y[k]<=m的序列,即为邮资区间
void f(int p,int r){
    //更新上一次邮票确定后的y
    //当然每次更新这一次也可以,但是代码有一些变化
    //因为y与具体的a的值有关,更确切的说,因为下列代码中有更新最小值,所以必须恢复y
    for(int i=0;i<=a[p-1]*n;i++){
        //对于 i-1 所有的邮资可能
        for(int j=1;j<=n-y[i];i++){
            if(y[i]+j<y[i+j*a[p-1]]) y[i+j*a[p-1]]=y[i]+j;
        }
    }
    // int r=0;
    //使用了r作为参数,这样就不用每次都扫描全部了
    while (y[r]<=n) r++;
    r--;
    //r即为当前区间最大值
    if(p>=k){
        if(r>MAX){
            MAX=r;
            memcpy(best,a,sizeof(a));
        } 
        return;
    }
    int z[10001];
    memcpy(z,y,sizeof(z));
    for(int i=a[p-1]+1;i<=r+1;i++){
        a[p]=i;
        f(p+1,r);
        memcpy(y,z,sizeof(z));
    }
}
int main(){
    cin>>n>>k;
    for(int i=0;i<=10001;i++) y[i]=INF;
    y[0]=0;
    if(k!=0){
        a[0]=1;
        f(1,1);
    }
    for(int i=0;i<k;i++) cout<<best[i]<<" ";
    cout<<endl;
    cout<<"MAX="<<MAX<<endl;
    return 0;
}

 

posted @ 2020-06-06 21:44  西伯利亚挖土豆  阅读(362)  评论(0编辑  收藏  举报