微软的扔杯子问题-动态规划
2015-05-01 20:54
302 查看
微软的扔杯子问题-动态规划
分类:Algorithm 2011-12-22 10:05
2754人阅读 评论(3)
收藏
举报
微软layer新浪微博测试面试
目录(?)[+]
在新浪微博上看到了一微软面试题
[b]题目描述[/b]
一种杯子,若在第N层被摔破,则在任何比N高的楼层均会破,若在第M层不破,则在任何比M低的楼层均不会破,给你两个这样的杯子,让你在100层高的楼层中测试,要求用最少的测试次数找出恰巧会使杯子破碎的楼层。
[b]不等式解法[/b]
所有讨论基于2个杯子的情况:
下图中所有图示的红线均表示剩下两个杯子的时候的试摔位置,当杯子破碎后,也就是只剩下一个杯子的时候,只需要从已知范围的最底层向已知范围的最高层逐层试摔。
当只有一层的时候,需要一次试摔。当有两层的时候,需要两次试摔。
当需要三层时候,首先讨论是否可以通过两次试摔完成,可以发现可以,方法如图。
当需要四层时候,首先讨论是否可以通过两次试摔完成,可以发现已经不行,因此至少需要三次试摔。
当需要五层时候,首先讨论是否可以通过小于等于三次试摔完成,如果不行则讨论最多四次试摔的情况。依次类推,如下图:
因此,当有100层的时候,最多需要n次试摔,使得 n+(n-1)+(n-2)+...+1 >= 100,然后对n上取整,因此n=14。最差情况需要14次试摔。试摔方法为:第一次在14层扔,如果没破,在27层(14+13)继续扔,不破在39层(27+12)继续扔,依次类推。 如果破了,剩下一个杯子,从已知范围的最底层向已知范围的最高层逐层试摔。
[b]动态规划解法[/b]
假设用dp[i][j]表示剩余i层,j个杯子时候最少需要多少次试摔。
(1)dp[i][1] = i,也就是说当只剩下一个杯子时,只能从第一层开始逐层向上试摔。
(2)dp[0][j] = 0,当只剩下0层时,只需要进行0次试摔。
(3)dp[1][j] = 1,当只剩下1层时,只需要进行1次试摔,前提是j>0
(4)dp[i][j] = min(1=<k<j)(max(dp[k-1][i-1], dp[j-k][i]) + 1),也就是当杯子破和不破的时候分成两个子问题,分别求解,之后求子问题试摔次数的最大和作为这种分解方法的试摔次数,之后取这些所有分拆子问题的方法中,使子问题和最小的方法。
route[i][j],表示剩下i层j个杯子时,下一次试摔的楼层。当j=1时,从这个范围内的最底层依次向最高层试摔。
[cpp]
view plaincopy
//dp.c
#include <stdio.h>
#define LAYER 101
#define CUP 3
int main(){
int dp[LAYER][CUP], route[LAYER][CUP], i, j, k;
for(i=1; i<LAYER; i++){
dp[i][1] = i;
dp[i][0] = 0;
}
for(i=1; i<CUP; i++){
dp[1][i] = 1;
route[1][i] = 0;
dp[0][i] = 0;
}
for(i=2; i<CUP; i++)
for(j=2; j<LAYER; j++){
dp[j][i] = j;
route[j][i] = 0;
for(k=1; k<j; k++){
int min = dp[k-1][i-1] > dp[j-k][i]? dp[k-1][i-1]+1: dp[j-k][i]+1;
route[j][i] = min <= dp[j][i]? k: route[j][i];
dp[j][i] = min < dp[j][i]? min: dp[j][i];
}
}
printf("MIN STEP IS %d\n", dp[LAYER-1][CUP-1]);
//for(i=1; i<LAYER; i++){for(j=2; j<CUP; j++){printf("%d\t", route[i][j]);} printf("\n");}
return 0;
}
输出结果为:MIN STEP IS 14。也就是,有一种方法,最多需要试摔14次。同时route数组打印出了方法。
比如route数组的结果:
1 | 0 | 2 | 1 | 3 | 2 | 4 | 3 | 5 | 3 |
6 | 3 | 7 | 4 | 8 | 4 | 9 | 4 | 10 | 4 |
11 | 5 | 12 | 5 | 13 | 5 | 14 | 5 | 15 | 5 |
16 | 6 | 17 | 6 | 18 | 6 | 19 | 6 | 20 | 6 |
21 | 6 | 22 | 7 | 23 | 7 | 24 | 7 | 25 | 7 |
26 | 7 | 27 | 7 | 28 | 7 | 29 | 8 | 30 | 8 |
31 | 8 | 32 | 8 | 33 | 8 | 34 | 8 | 35 | 8 |
36 | 8 | 37 | 9 | 38 | 9 | 39 | 9 | 40 | 9 |
41 | 9 | 42 | 9 | 43 | 9 | 44 | 9 | 45 | 9 |
46 | 10 | 47 | 10 | 48 | 10 | 49 | 10 | 50 | 10 |
51 | 10 | 52 | 10 | 53 | 10 | 54 | 10 | 55 | 10 |
56 | 11 | 57 | 11 | 58 | 11 | 59 | 11 | 60 | 11 |
61 | 11 | 62 | 11 | 63 | 11 | 64 | 11 | 65 | 11 |
66 | 11 | 67 | 12 | 68 | 12 | 69 | 12 | 70 | 12 |
71 | 12 | 72 | 12 | 73 | 12 | 74 | 12 | 75 | 12 |
76 | 12 | 77 | 12 | 78 | 12 | 79 | 13 | 80 | 13 |
81 | 13 | 82 | 13 | 83 | 13 | 84 | 13 | 85 | 13 |
86 | 13 | 87 | 13 | 88 | 13 | 89 | 13 | 90 | 13 |
91 | 13 | 92 | 14 | 93 | 14 | 94 | 14 | 95 | 14 |
96 | 14 | 97 | 14 | 98 | 14 | 99 | 14 | 100 | 14 |
相关文章推荐
- 微软的扔杯子问题-动态规划
- 微软的扔杯子问题-动态规划
- 动态规划解最长公共子序列问题
- 0-1背包问题(动态规划)
- poj 3311(浅谈状态压缩动态规划在解决TSP问题中的应用)
- 关于微软网站后缀名是mspx的问题
- 动态规划求解合唱队问题的思路
- 动态规划(DP)问题状态方程合集
- 微软201604笔试题目3 Demo Day 动态规划解法
- 什么是 “动态规划” , 用两个经典问题举例。
- 动态规划、贪心、回溯、分支限界法解0-1背包问题总结
- POJ 1042 钓鱼问题 贪心枚举及动态规划
- 动态规划:求最长公共子序列问题
- 整数划分 --- 一个老生长谈的问题 动态规划
- 微软的谍件问题
- 普及练习场 动态规划的背包问题 金明的预算方案
- 51nod 最长公共子序列问题(动态规划)(LCS)(递归)
- 【原】动态规划——石子划分问题
- 安装win10后电脑被劫持怎么办?微软的Windows 10免费升级邮件轻松解决问题
- 0/1背包问题----动态规划实现