【题目描述】
给定一个信封,最多只允许粘贴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分。
【输入描述】
N和K。
【输出描述】
每种邮票的面值,连续最大能到的面值数。数据保证答案唯一。
【样例输入】
3 2
【样例输出】
1 3
MAX=7
源代码: #include<cstdio> #define INF 100000000 int n,k,ans(0),h[40],i[40],f[4000001]; void DP() //DP出此情况的最大连续值,并更新最终结果。 { int num(0); f[0]=0; while (f[num]<=n) { num++; f[num]=INF; for (int a=1;a<=k&&num>=h[a];a++) if (f[num]>f[num-h[a]]+1) f[num]=f[num-h[a]]+1; } if (num-1>ans) { ans=num-1; for (int a=1;a<=k;a++) //答案数组。 i[a]=h[a]; } } void DFS(int t) //深搜各种情况。 { if (t==k+1) //新情况的构建已经完成,开始检验。 { DP(); return; } for (int a=h[t-1]+1;a<=h[t-1]*n+1;a++) //神奇的范围。 { h[t]=a; //小白鼠数组。 DFS(t+1); //已完成构建新情况的一步。 } } int main() //一足失成千古恨。 { scanf("%d%d",&n,&k); DFS(1); for (int a=1;a<=k;a++) printf("%d ",i[a]); printf("\nMAX=%d",ans); return 0; } /* 神妙的范围: 用样例举例来说: 如果1想要和N构成合法的一组情况,则N=2,3,4。因为1和2这是毫无疑问的了,三张邮票都是1的面值为3,若想要连续,则应为3+1=4。 以此类推: h[i] ----> [h[i-1]+1(上一步),h[i-1]*n+1]。 */