软件大赛题目之回溯

题目描述:

公司发了某商店的购物券1000元,限定只能购买店中的m种商品。每种商品的价格分别为m1,m2,…,要求程序列出所有的正好能消费完该购物券的不同购物方法。
程序输入:
第一行是一个整数m,代表可购买的商品的种类数。
接下来是m个整数,每个1行,分别代表这m种商品的单价。
程序输出:
第一行是一个整数,表示共有多少种方案
第二行开始,每种方案占1行,表示对每种商品购买的数量,中间用空格分隔。


例如:
输入:
2
200
300
则应输出:
2
2  2
5  0
输入:
2
500
800
则应输出:
1
2  0

  1 // 代码一:---自己写的
  2 //-----我用dev编译不通过,全局数组count在递归中不被识别,
  3 //不知道为啥,VC 6.0就能通过,    求解释???
  4 
  5 #include <iostream>
  6 #include <cstdio>
  7 #include <cstring>
  8 
  9 using namespace std;
 10 
 11 int count[1000]; //  记录每种物品选择的个数
 12 int num, n;   // 记录总共的方案数量
 13 int ans[1000][1000];  // 记录方案的 矩阵
 14 int price[100];
 15 
 16 void search(int cur, int sum, int money)
 17 {
 18     if(sum == money)  // sum 表示当前花费
 19     {
 20         for(int i = 0; i < n; ++i)
 21             ans[num][i] = count[i];
 22         ++num;
 23         return;
 24     }
 25     if(sum > money || cur >= n)
 26         return;
 27 
 28     //  选择一个第 cur 种 物品
 29     sum += price[cur];
 30     ++count[cur];
 31     search(cur, sum, money);
 32 
 33     //  不选择一个第 cur 种 物品
 34     sum -= price[cur];
 35     --count[cur];
 36     search(cur + 1, sum, money);
 37 }
 38 
 39 int main()
 40 {
 41     while(~scanf("%d", &n))
 42     {
 43 
 44         for(int i = 0; i < n; ++i)
 45             for(int j = 0; j < n; ++j)
 46                 ans[i][j] = 0;
 47         memset(count, 0, sizeof(count));
 48         num = 0;
 49         for(int i = 0; i < n; ++i)
 50             scanf("%d", &price[i]);
 51         search(0, 0, 1000);
 52         printf("%d\n", num);
 53         for(int i = 0; i < num; ++i)
 54         {
 55             for(int j = 0; j < n; ++j)
 56                 printf("%d ", ans[i][j]);
 57             printf("\n");
 58         }
 59     }
 60     return 0;
 61 }
 62 */
 63 
 64 // 代码二:
 65 #include <stdio.h>
 66 
 67 int sln;//方案的个数
 68 int gm;//商品的种类
 69 int price[1000];//各种商品价钱
 70 int count[1000];//各种商品的个数
 71 int method[1000][1000];//每种解决方案中各商品的个数
 72 int cost;//当前花费
 73 void output()//输出解决方案
 74 {
 75     int i,j;
 76     printf("%d\n",sln);
 77     for (i=0; i<sln; i++)
 78     {
 79         for (j=0;j<gm;j++)
 80             printf("%3d",method[i][j]);
 81         printf("\n");
 82     }
 83 }
 84 void fun(int m)
 85 {
 86     int i;
 87     if (cost == 1000)
 88     {
 89         for (i=0; i<gm ; i++)
 90             method[sln][i] = count[i];
 91         sln++;
 92         return;
 93     }
 94     if (cost>1000 || m<0)
 95         return;
 96     //choose m
 97     ++count[m];
 98     cost += price[m];
 99     fun(m);
100     //not choose m
101     --count[m];
102     cost -= price[m];
103     fun(m-1);
104 }
105 void main()
106 {
107     int m;//商品的种类
108     int k;
109 
110     scanf("%d",&m);
111     gm=m;
112     for (k=0;k<m;k++)
113         scanf("%d",&price[k]);
114     fun(m-1);
115     output();
116 }

 代码三:------------------复习回顾

 1 #include <cstdio>
 2 #include <iostream>
 3 #include <cstring>
 4 
 5 using namespace std;
 6 
 7 int res[1000][1000], tmp[1000], price[1000];
 8 
 9 int cnt, n;
10 
11 void DFS(int left, int pos)
12 {
13     if(left == 0)
14     {
15         for(int i = 0; i <= pos; ++i)
16             res[cnt][i] = tmp[i];
17         ++cnt;
18         return;
19     }
20     if(left < price[pos] || pos >= n)
21         return;
22     if(left >= price[pos])
23     {
24         tmp[pos]++;
25         DFS(left-price[pos], pos);
26         tmp[pos]--;
27         DFS(left, pos+1);
28     }
29 }
30 
31 void Output()
32 {
33     printf("%d\n", cnt);
34     for(int i = 0; i < cnt; ++i)
35     {
36         for(int j = 0; j < n-1; ++j)
37             printf("%d ", res[i][j]);
38         printf("%d\n", res[i][n-1]);
39     }
40 }
41 
42 int main()
43 {
44     freopen("in.txt", "r", stdin);
45     //freopen("out.txt", "w", stdout);
46     while(~scanf("%d", &n))
47     {
48         for(int i = 0; i < n; ++i)
49             scanf("%d", &price[i]);
50         cnt = 0;
51         memset(tmp, 0, sizeof(tmp));
52         DFS(1000, 0);
53         Output();
54     }
55     while(1);
56     return 0;
57 } 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值