邮票面值设计

博客围绕搜索与DP展开,探讨当前枚举的邮票面值所能构成的最大值求解问题。指出最大面值为k时,maxx达不到k不一定不合法。大体思路是用dfs确定邮票面值,用DP求当前邮票能构成的最大值,而非简单用max*k。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

搜索+DP

思路还是有一点点问题的。就是关于当前枚举的邮票的面值所能构成的最大值的求解:

假如最大的面值为\(k\),那么\(maxx\)达不到\(k\),不一定不合法,不能直接$return $。

大体思路:

\(dfs\)每张邮票的面值,求出当前邮票所能构成的最大值(不是直接\(max*k\),这里用DP,再写搜索太\(low\)了。

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int n,k,ans=0,f[20],v[20];
bool book[100005];
void dfsc(int u,int ansp)
{
    book[ansp]=1; 
    if(u>=n) { return ;}
    for(int i=1;i<=k;++i)
     dfsc(u+1,ansp+f[i]);
}
int check(int anst)
{
    for(int i=1;i<=anst;i++) book[i]=0;
    dfsc(0,0);
    for(int i=1;i<=anst;i++)
     if(!book[i]) return 0;
    while(book[anst]) ++anst;
    --anst;
    return anst;
}
void print(int val)
{//cout<<"*"<<endl;
    if(val>ans)
    {
        ans=val;
        for(int i=1;i<=k;i++)
         v[i]=f[i];
    }
    return ;
}
void dfs(int t,int maxx,int last)
{//cout<<t<<"*"<<maxx<<"&"<<last<<endl;
//  if(!check(maxx)) return ;
    if(t==0) { f[1]=1; dfs(1,n,1); return ;}
    maxx=check(maxx);
    if(!maxx) return ;
    print(maxx); 
    if(t>=k) { return; }
    for(int i=last+1;i<=maxx+1;i++)
    {
        f[t+1]=i;
        dfs(t+1,i*k,i);
    }
}
int main()
{
    scanf("%d%d",&n,&k);
    dfs(0,0,0);
    for(int i=1;i<=k;i++)
     printf("%d ",v[i]);
    printf("\n");
    printf("MAX=%d\n",ans);
    return 0;
}

0分,www.......

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int n,k,res,ans[105],tmp[105],dp[2005];
int num(int dep,int sum)
{
    memset(dp,0x3f,sizeof(dp));
    dp[0]=0;
    for(int i=1;i<=dep;i++)
     for(int j=tmp[i];j<=n*sum;j++)
      dp[j]=min(dp[j],dp[j-tmp[i]]+1);
    for(int i=1;i<=n*sum;i++)
     if(dp[i]>n)
      return i-1;
    return n*sum;
}
void dfs(int dep,int last1,int last2,int sum)
{
    if(dep>k)
    {
        if(res<last2)
        {
            res=last2;
            for(int i=1;i<=k;i++)
             ans[i]=tmp[i];
        }
        return ;
    }
    for(int i=last1+1;i<=last2+1;i++)
    {
        tmp[dep]=i;
        int x=num(dep,sum+i);
        dfs(dep+1,i,x,sum+i);
    }
}
int main()
{
    scanf("%d%d",&n,&k);
    dfs(1,0,0,0);
    for(int i=1;i<=k;i++)
     printf("%d ",ans[i]);
    printf("\nMAX=%d\n",res);
    return 0;
}

转载于:https://www.cnblogs.com/karryW/p/10809713.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值