组队赛(第7周) (动态规划扔鸡蛋问题)

E(动态规划扔鸡蛋)

4554 Balls
The classic Two Glass Balls brain-teaser is often posed as:
“Given two identical glass spheres, you would like to determine the lowest floor in a 100-story
building from which they will break when dropped. Assume the spheres are undamaged
when dropped below this point. What is the strategy that will minimize the worst-case
scenario for number of drops?”
Suppose that we had only one ball. We’d have to drop from each floor from 1 to 100 in sequence,
requiring 100 drops in the worst case.
Now consider the case where we have two balls. Suppose we drop the first ball from floor n. If it
breaks we’re in the case where we have one ball remaining and we need to drop from floors 1 to n − 1
in sequence, yielding n drops in the worst case (the first ball is dropped once, the second at most n − 1
times). However, if it does not break when dropped from floor n, we have reduced the problem to
dropping from floors n + 1 to 100. In either case we must keep in mind that we’ve already used one
drop. So the minimum number of drops, in the worst case, is the minimum over all n.
You will write a program to determine the minimum number of drops required, in the worst case,
given B balls and an M -story building.
Input
The first line of input contains a single integer P , (1 ≤ P ≤ 1000), which is the number of data sets that
follow. Each data set consists of a single line containing three (3) decimal integer values: the problem
number, followed by a space, followed by the number of balls B, (1 ≤ B ≤ 50), followed by a space and
the number of floors in the building M , (1 ≤ M ≤ 1000).
Output
For each data set, generate one line of output with the following values: The data set number as a
decimal integer, a space, and the minimum number of drops needed for the corresponding values of B
and M .
Sample Input
4
1
2
3
4
2 10
2 100
2 300
25 900
Sample Output
1   4
2   14
3   24
4   10

这题就是很出名的扔鸡蛋问题,不过这道题改成了玻璃球。

想要找到,在最坏的情况下,我们所需要的检测次数最少来找到鸡蛋在哪一楼层之下,鸡蛋不会被摔碎,输出最少的次数。

一共有m个鸡蛋,n层楼,dp[m][n]表示有m个鸡蛋,需要检测的层数有n层。

首先我们要确立最坏的情况,

假设我们在1 to n层中任选一层扔下鸡蛋,假设在第i层扔下,1:如果鸡蛋在第i层碎掉了,还剩m-1个鸡蛋,现在只需要 在1 to i-1层中检测,剩下i-1个楼层需要检测,dp[m][i] = dp[m-1][i-1] + 1,1表示第i层的检测。2:如果鸡蛋在第i层没有碎,还剩m个鸡蛋,现在只需要在i+1 to n层中检测,剩下n-i个楼层需要检测,dp[m][i] = dp[m][n-1] + 1,1表示第i层的检测。最坏的情况就是,两种情况之下,所需要检测的次数最多的那一种情况。

然后找到在(1,n)层中,从哪层扔下所需次数最少的情况。

 1 #include<cstdio>
 2 #include<algorithm>
 3 using namespace std;
 4 int dp[1001][1001];
 5 int judge_(int a,int b){
 6     for(int i = 0; i <=b; ++i) {
 7         dp[0][i] = 0;//如果没有鸡蛋,需要的次数都为0
 8         dp[1][i] = i;//如果鸡蛋只有一个,那么需要的次数就是楼层数
 9     }
10     for(int i = 2; i <= a; ++i) {
11         dp[i][0] = 0;//如果没有楼层,所需要的次数是0
12         dp[i][1] = 1;//如果只有1个楼层,所需要的次数是1
13     }
14     for(int i = 2; i <= a; ++i) {//鸡蛋从2 to a 遍历
15         for(int j = 2; j <= b;j++) {//楼层从2, to b遍历,dp[i][j]表示,在有i个鸡蛋,j个楼层需要检测的情况下所需要的最小检测次数
16             int  t = 0x3f3f3f;
17             for(int k = 1; k <= j; ++k) {//找到1 to j从哪一个楼层扔下所需要的次数最少
18                  t = min(t,1 + max(dp[i-1][k-1],dp[i][j-k]));// max(dp[i-1][k-1],dp[i][j-k]) 找到碎和不碎的情况下,所需要的最大的次数,即最坏的情况
19             }
20             dp[i][j] = t;//将最小的次数赋值给在有i个鸡蛋,j个楼层需要检测的情况下的最小次数
21         }
22     }
23     return dp[a][b];//输出在有a个鸡蛋,b个楼层需要检测的情况下的需要的最小次数
24 }
25 int main()
26 {
27     int p;
28     scanf("%d",&p);
29     while (p--) {
30         int  n,a,b;
31         scanf("%d %d %d",&n,&a,&b);
32         printf("%d %d\n",n,judge_(a,b));
33     }
34     return 0;
35 }

 贴一个写的比较好的博客吧

https://blog.csdn.net/joylnwang/article/details/6769160

 

F - Adjacent Bit Counts

4557 Adjacent Bit Counts
For a string of n bits x 1 , x 2 , x 3 ,..., x n , the adjacent bit count of the string (AdjBC(x)) is given by
x 1 ∗ x 2 + x 2 ∗ x 3 + x 3 ∗ x 4 + . . . + x n−1 ∗ x n
which counts the number of times a 1 bit is adjacent to another 1 bit. For example:
AdjBC(011101101) = 3
AdjBC(111101101) = 4
AdjBC(010101010) = 0
Write a program which takes as input integers n and k and returns the number of bit strings x of n
bits (out of 2 n ) that satisfy AdjBC(x) = k. For example, for 5 bit strings, there are 6 ways of getting
AdjBC(x) = 2:
11100, 01110, 00111, 10111, 11101, 11011
Input
The first line of input contains a single integer P , (1 ≤ P ≤ 1000), which is the number of data sets that
follow. Each data set is a single line that contains the data set number, followed by a space, followed by
a decimal integer giving the number (n) of bits in the bit strings, followed by a single space, followed by
a decimal integer (k) giving the desired adjacent bit count. The number of bits (n) will not be greater
than 100 and the parameters n and k will be chosen so that the result will fit in a signed 32-bit integer.
Output
For each data set there is one line of output. It contains the data set number followed by a single space,
followed by the number of n-bit strings with adjacent bit count equal to k.
Sample Input
10
1 5 2
2 20 8
3 30 17
4 40 24
5 50 37
6 60 52
7 70 59
8 80 73
9 90 84
10 100 90
Sample Output
1 6
2 63426
3 1861225
4 168212501
5 44874764
6 160916
7 22937308
8 99167
9 15476
10 23076518

题意:给你一个长为n的串,且仅有0和1组成,x 1 ∗ x 2 + x 2 ∗ x 3 + x 3 ∗ x 4 + . . . + x n−1 ∗ x n 这样计算的值等于k,问该字符串有多少种这样的组合?

分析:用动态规划的思想,假如dp[i][j][k]表示组合数,i表示字串长度,j表示该串价值,k表示最后一个字符只能为1和0。

dp[i][j][0],有i个字符,价值为j,最后一位为0,这样的组合数等于长度为i-1,价值为j,最后一位为0的组合数加上长度为i-1,价值为j,最后一位为1的组合数,即dp[i][j][0]=dp[i-1][j][0]+dp[i-1][j][1]。

dp[i][j][1],有i个字符,价值为j,最后一位为1,这样的组合数等于长度为i-1,价值为j,最后一位为0的组合数加上长度为i-1,价值为j-1,最后一位为1的组合数,即dp[i][j][1]=dp[i-1][j][0]+dp[i-1][j-1][1]。

总结下来状态转移方程即是:

dp[i][j][0]=dp[i-1][j][0]+dp[i-1][j][1]

dp[i][j][1]=dp[i-1][j][0]+dp[i-1][j-1][1]

再说说初始化

长度为1的时候,没有其他的数和它相乘,所以价值只能为0

dp[1][0][0]=1;长度为1价值为0且最后一位为0的组合数只有1种,比如0

dp[1][0][1]=1;长度为1价值为0且最后一位为1的组合数只有1种,比如1

看了别人题解,都说这是很简单的动规,佩服佩服

 

 1 #include<cstdio>
 2 #include<algorithm>
 3 using namespace std;
 4 int dp[105][105][2];//dp定义为全局变量
 5 void find_(){
 6      dp[1][0][0]=dp[1][0][1]=1;//初始化
 7      for(int i=2;i<105;i++){//每一个长度时,都需要初始化一遍
 8             dp[i][0][0]=dp[i-1][0][1]+dp[i-1][0][0];
 9             dp[i][0][1]=dp[i-1][0][0];
10         for(int j=1;j<i;j++){//长度为i时,价值最多为i-1
11             dp[i][j][0]=dp[i-1][j][1]+dp[i-1][j][0];
12             dp[i][j][1]=dp[i-1][j][0]+dp[i-1][j-1][1];
13         }
14      }
15 }
16 int main() {
17     int p;
18     find_();
19     scanf("%d",&p);
20     while(p--) {
21         int n,a,b;
22         scanf("%d %d %d",&n,&a,&b);
23         printf("%d %d\n",n,dp[a][b][0]+dp[a][b][1]);
24     }
25     return 0;
26 }
CUTECode

 

转载于:https://www.cnblogs.com/LLLAIH/p/9794788.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值