邮票面值设计——深搜+dp剪枝

                                                                                                                           连续邮资问题
Time Limit: 1500 ms    Memory Limit: 10000 kB  
Total Submit : 59 (25 users)   Accepted Submit : 22 (16 users)   Page View : 3748 

 

G国发行了n种不同面值的邮票,并且规定每张信封上最多只允许贴m张邮票。连续邮资问题要求对于给定的n和m的值,给出邮票面值的最佳设计,使得可在1张信封上贴出从邮资1开始,增量为1的最大连续邮资区间。例如,当n=5和m=4时,面值为( 1,3,11,15,32)的5种邮票可以贴出邮资的最大连续邮资区间是1到70。编程任务: 对于给定的正整数m和n,计算出邮票面值的最佳设计。

Input

输入数据每一行给出2个正整数m和n的值( 1<=n,m<=9),最后以0 0 表示文件结束。

Output

对于输入中每一行的正整数m和n,将最大连续邮资区间输出。

Sample Input

4 5
0 0

Sample Output

70
http://acm.nankai.edu.cn/p1428.html

分析:这是一道深搜加dp剪枝的题。但即使这样,仍然效率不高。当然在这里提交是过了。

 

代码
   
     
1 #include < stdio.h >
2 #include < stdlib.h >
3 #include < string .h >
4 int n,m,f[ 1000000 ] = { 0 },max,ma,s[ 100 ],limit,flag[ 1000000 ] = { 0 };
5 int dp( int k){
6 int i,j;
7 for (j = 1 ;j <= m * limit;j ++ )
8 f[j] = m + 1 ;
9 for (j = 1 ;j <= m * limit;j ++ )
10 {
11 for (i = 1 ;i <= k;i ++ )
12 if (j >= s[i])
13 if (f[j] > f[j - s[i]] + 1 )f[j] = f[j - s[i]] + 1 ;
14 if (f[j] > m)
15 {
16 if (k == n)ma = j - 1 ;
17 return j;
18 }
19 }
20 return j;
21 }
22
23 void dfs( int x, int k){
24 int i,j,z;
25 if (k <= n)
26 for (i = 2 ;i <= x;i ++ )
27 if (flag[i] != 1 )
28 {
29 s[k] = i;
30 flag[i] = 1 ;
31 if (i > limit)limit = i;
32 z = dp(k);
33 if (k == n && max < ma)
34 max = ma;
35 dfs(z,k + 1 );
36 flag[i] = 0 ;
37 }
38 }
39
40 int main(){
41 scanf( " %d%d " , & m, & n);
42 while (m + n != 0 )
43 {
44 max = 0 ;limit = 1 ;
45 int i,j,x;
46 s[ 1 ] = 1 ;flag[ 1 ] = 1 ;
47 ds(m + 1 , 2 );
48 printf( " %d\n " ,max);
49 scanf( " %d%d " , & m, & n);
50 }
51 return 0 ;
52 }

 

你可能感兴趣的:(dp)