8.4 智力趣题(1)

8-13 hanoi1.c

 1 #include <stdio.h>
 2 long count; //全局变量, 记录移动的次数
 3 void hanoi(int n,char a,char b,char c) //a移到b,用c作临时柱
 4 {
 5     if(n==1)
 6     {
 7        printf("第%d次,%c棒-->%c棒\n",++count,a,c);
 8     }
 9     else
10     {
11         hanoi(n-1,a,c,b); //递归调用本函数,移动a到c,用b作临时柱
12         printf("第%d次,%c棒-->%c棒\n",++count,a,c);
13         hanoi(n-1,b,a,c); //递归调用本函数,将b移到a,用c作临时柱
14     }
15 }
16 int main()
17 {
18     int h; //圆盘数量
19     printf("请输入汉诺塔圆盘的数量:");
20     scanf("%d",&h);
21     count=0;
22     hanoi(h,‘A‘,‘B‘,‘C‘);
23     getch();
24     return 0;
25 }

8-14 hanoi2.c

 1 #include <stdio.h>
 2 #define MAX 64 //最多64个圆盘
 3 int main()
 4 {
 5    int n, target, source, i, array[(MAX+1)*3+1], stick[3],height;
 6    long count=0;//圆盘移动的次数
 7    printf("请输入汉诺塔圆盘的数量:");
 8    scanf("%d", &n); //输入盘子数量
 9    height=n+1;//棒的高度(用来分隔数组)
10    for (i = 1; i <= n; i++)    //将盘子放入第1个柱子
11       array[i] = height - i; //数字大的表示大盘子
12    for (i = 0; i <= 2 * height; i += height)    //将每个柱的底部设置为一个大的数据
13       array[i] = 1000;
14    if (n % 2 == 0) //若圆盘序号是偶数
15    {
16       target = 1; //目标为B棒
17       stick[2] = 0;
18       stick[1] = 1;
19       array[height + 1] = array[n]; //移动第1个圆盘到第2个柱
20    }
21    else //若圆盘序号为奇数
22    {
23       target = 2; //目标为C棒
24       stick[1] = 0;
25       stick[2] = 1;
26       array[2 * height + 1] = array[n]; //移动第1个圆盘到第3个柱
27    }
28    printf("第%d次,A棒-->%c棒\n",++count,‘A‘-1+target+1);  //输出移动操作
29    stick[0] = n - 1; //A棒中减去一个圆盘
30    while(stick[0] + stick[1])    //第1棒和第2棒不为空,则循环移动
31    {
32       if (target == 0) //若目标棒是A
33       {
34           if (array[height + stick[1]] < array[2 * height + stick[2]])//比较B、C柱的较小值作为下一个移动柱
35               source = 1;
36           else
37               source = 2;
38       }
39       if (target == 1)//若目标棒是B
40       {
41           if(array[stick[0]] < array[2 * height + stick[2]]) //比较A、C柱的较小值
42               source = 0;
43           else
44               source = 2;
45       }
46       if (target == 2)//若目标棒是C
47       {
48           if(array[stick[0]] < array[height + stick[1]]) //比较A、B柱的较小值
49               source= 0;
50           else
51               source= 1;
52       }
53 // 将source柱顶部圆盘移到另一较大或为偶数的棒
54       if ((array[source * height + stick[source]]) > (array[target * height + stick[target]])
55          || ((array[target * height + stick[target]] - array[source * height + stick[source]]) % 2 ==0))
56          target = 3 - source - target;
57       printf("第%d次,%c棒-->%c棒\n",++count,‘A‘-1+source+1,‘A‘-1+target+1);  //输出移动操作
58       stick[source] = stick[source] - 1;
59       stick[target] = stick[target] + 1;    //从source棒移动target棒
60       array[target * height + stick[target]] = array[source * height + stick[source] + 1];
61    }
62    getch();
63    return 0;
64 }

8-15 backpack1.c

 1 #include <stdio.h>
 2 typedef struct goods
 3 {
 4     double *value; //价值
 5     double *weight; //重量
 6     char *select; //是否选中到方案
 7     int num;//物品数量
 8     double limitw; //限制重量
 9 }GOODS;
10 double maxvalue,totalvalue;//方案最大价值,物品总价值
11 char *select1; //临时数组
12 void backpack(GOODS *g, int i, double tw, double tv)//参数为物品i,当前选择已经达到的重量和tw,本方案可能达到的总价值
13 {
14    int k;
15    if (tw + g->weight[i] <= g->limitw)//将物品i包含在当前方案,且重量小于等于限制重量
16    {
17       select1[i] = 1; //选中第i个物品
18       if (i < g->num - 1) //若物品i不是最后一个物品
19          backpack(g, i + 1, tw + g->weight[i], tv); //递归调用,继续添加下一物品
20       else //若已到最后一个物品
21       {
22          for (k = 0; k < g->num; ++k) //将状态标志复制到option数组中
23             g->select[k] = select1[k];
24          maxvalue = tv; //保存当前方案的最大价值
25       }
26    }
27    select1[i] = 0; //取消物品i的选择状态
28    if (tv - g->value[i] > maxvalue)//若物品总价值减去物品i的价值还大于maxv方案中已有的价值,说明还可以继续向方案中添加物品
29    {
30       if (i < g->num - 1) //若物品i不是最后一个物品
31          backpack(g, i + 1, tw, tv - g->value[i]); //递归调用,继续加入下一物品
32       else //若已到最后一个物品
33       {
34          for (k = 0; k < g->num; ++k) //将状态标志复制到option数组中
35             g->select[k] = select1[k];
36          maxvalue = tv - g->value[i]; //保存当前方案的最大价值(从物品总价值中减去物品i的价值)
37       }
38    }
39 }
40 int main()
41 {
42    double sumweight;
43    GOODS g;
44    int i;
45    printf("背包最大重量:");
46    scanf("%lf",&g.limitw);
47    printf("可选物品数量:");
48    scanf("%d",&g.num);
49    if(!(g.value = (double *)malloc(sizeof(double)*g.num)))//分配内存保存物品价值
50    {
51        printf("内存分配失败\n");
52        exit(0);
53    }
54    if(!(g.weight = (double *)malloc(sizeof(double)*g.num)))//分配内存保存物品的重量
55    {
56        printf("内存分配失败\n");
57        exit(0);
58    }
59    if(!(g.select = (char *)malloc(sizeof(char)*g.num)))//分配内存保存物品的重量
60    {
61        printf("内存分配失败\n");
62        exit(0);
63    }
64    if(!(select1 = (char *)malloc(sizeof(char)*g.num)))//分配内存保存物品的重量
65    {
66        printf("内存分配失败\n");
67        exit(0);
68    }
69    totalvalue=0;
70    for (i = 0; i < g.num; i++)
71    {
72       printf("输入第%d号物品的重量和价值:",i + 1);
73       scanf("%lf%lf",&g.weight[i],&g.value[i]);
74       totalvalue+=g.value[i];//统计所有物品的价值总和
75    }
76    printf("\n背包最大能装的重量为:%.2f\n\n",g.limitw);
77    for (i = 0; i < g.num; i++)
78       printf("第%d号物品重:%.2f,价值:%.2f\n", i + 1, g.weight[i], g.value[i]);
79    for (i = 0; i < g.num; i++)//初始设各物品都没加入选择集
80        select1[i]=0;
81    maxvalue=0;//加入方案物品的总价值
82    backpack(&g,0,0.0,totalvalue); //第0号物品加入方案,总重量为0,所有物品价值为totalvalue
83    sumweight=0;
84    printf("\n可将以下物品装入背包,使背包装的物品价值最大:\n");
85    for (i = 0; i < g.num; ++i)
86       if (g.select[i])
87       {
88          printf("第%d号物品,重量:%.2f,价值:%.2f\n", i + 1, g.weight[i], g.value[i]);
89          sumweight+=g.weight[i];
90       }
91    printf("\n总重量为: %.2f,总价值为:%.2f\n", sumweight, maxvalue );
92    getch();
93    return 0;
94 }
时间: 2024-12-10 10:48:30

8.4 智力趣题(1)的相关文章

智力趣题几则

古时一位农民被人诬陷,农民据理力争,县官因已经接受别人的贿赂,不肯放人,又找不到理由,就出了个坏主意.叫人拿来十张纸条,对农民说:“这里有十张纸条,其中有九张写的‘死’, 一张写的‘生’,你摸一张,如果是‘生’,立即放你回去,如果是‘死’,就怪你命不好,怨不得别人.”聪明的农民早已猜到纸条上写的都是“死”,无论抓哪一张都一样.于是他想了个巧妙的办法,结果死里逃生了.你知道他想的什么办法吗? 把其中的一张纸条吃下去,再根据排除法,结果就有九张死那么它吃下去的就是“生” 称苹果         有十

8.4 智力趣题(2)

8-18 knight2.c 1 #include <stdio.h> 2 typedef struct coord 3 { 4 int x; 5 int y; 6 }Coordinate; //棋盘上的坐标 7 int chessboard[8][8] = { 0 }; //初始化棋盘各单元格状态 8 int curstep; //马跳的步骤序号 9 Coordinate move[8] = { {-2, 1}, {-1, 2}, {1, 2}, {2, 1}, 10 {2, -1}, {1

序列相关的趣题 之四

(8) 给定一个英文单词,消除其中重复的字母,只能删掉字母,不能交换字母顺序,最后原单词中每个字母只出现一次,求字典序最小的结果. 这是toj一个题,百度面试也问过,原题见 http://acm.tju.edu.cn/toj/showp3257.html 此题我非常喜欢,巧妙之处是其算法是O(n)的-- .我们一个字母一个字母加入序列,一旦来了一个比较"小"的字母,因为我们需要字典顺序最小,我们希望它尽可能靠前.所以我们试图"冒泡"似的把小的往前面送,经过尾部那些较

序列相关的趣题 之二

(4)数组中找到两个数和的绝对值最小 像不像2-SUM? 不多解释,主要是绝对值大的动就行,两头扫的方法真好!当然要先排序,出去排序就是O(n),算上排序的话退化到O(nlogn) 这也是codility上的问题,还没来得及整理. 上个代码: // you can also use includes, for example: // #include <algorithm> #include <algorithm> int ab(int x) { return (x >= 0

uyhip 趣题 拉灯问题总有解吗?

这是一个让我纠结许久,又不甘放弃的puzzle.在一个意志力极度薄弱的下午,对不起,我看了答案...所以,这又是一篇马后炮文章.但不是所有马后炮都一文不值.如果在讲解一个解答的时候,我们不能把思考背后的动机讲清楚,于他人和自己的价值就会小很多.每一步推理的过程,每一个构造的细节,不是无迹可寻的.我希望去揭示背后的东西. 一个解答背后包含了大量的探索.解谜高手对于如何避免无效的思考,摸清靠谱的思路,总是有一套自己的办法.遗憾的是,好些同学由于各种原因,没有公开自己的方法.例如,高斯同学,他认为数学

趣题[0]

趣题[0] 来源 17级老学长的作业题 题面 \(n\) 个物品,有两种值\(a[i]\)和\(b[i]\),给定\(k\).从中选出一些物品,使得 \(\sum{a[i]} = k * \sum{b[i]}\),并且 \(\sum{a[i]}\) 尽量大,求满足条件的最大的 \(\sum{a[i]}\). \(1 <= n.a[i].b[i] <= 100\) \(1 <= k <= 10\) 题解 做差值之后分正负做背包,然后扫一遍即可. 复杂度 \(O(100 * k * n

趣题[1]

趣题[1] 来源 http://www.csie.ntnu.edu.tw/~u91029/Sequence3.html UVA - 12192 介绍 引入 \(n*m\)的矩阵,每行从左到右递增,每列从上到下递增,在矩阵中找数\(x\)出现过的位置. 具体做法可以在这个链接ctrl+F[Search in Sorted Matrix: Saddleback Search],复杂度\(O(n+m)\) 想法 现在我们知道了,从这样的矩阵的右上角走下来可以把矩阵分成两个部分,左上部分小于\(x\),

算法趣题之回文数

题目:求用十进制.二进制.八进制表示都是回文数的所有数字中,大于十进制数10的最小值. 啥叫回文数:如果把某个十进制数按相反的顺序排列,得到的数和原来的数相同,则这个数就是"回文数".例如12321就是一个回文数. 这个题目拿Ruby.JavaScript.python.Java都很容易实现,因为这些语言都提供了字符串逆序处理的接口,或者相关其他接口,而C语言没有提供直接转换的接口,所以下面用C语言解题,其中设计的封装在工作中也会经常碰到,故记录并分享,如有错误或者有更好的算法,欢迎留

趣题——“1”的个数

题目:编写一个函数,确定一个整数的计算机内部表示中有多少个"1". 方法一: 思路: 这个问题看上去是一个简单的转换题,即将一个十进制转换为二进制.但事实上,任何一个数字在计算机中已经是二进制表示了.因此,不再需要显式地使用程序将其转换.对于一个二进制,有多少个1,可以从低位开始数.即每次右移一位,并判断移除的这一位是否为1,直到右移结果为0为止. 例如: 在100101 中, 1. 将其与000001 做与运算,得到最后一位,为1; 2. 右移一位,得到10010; 3. 重复步骤1