搜索+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("
");
printf("MAX=%d
",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)
{
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,i);
dfs(dep+1,i,x);
}
}
int main()
{
scanf("%d%d",&n,&k);
dfs(1,0,0);
for(int i=1;i<=k;i++)
printf("%d ",ans[i]);
printf("
MAX=%d
",res);
return 0;
}