贴一个别人写的:https://blog.csdn.net/hebtu666/article/details/84789853
import java.util.Scanner;
/* x星球的居民脾气不太好,但好在他们生气的时候唯一的异常举动是:摔手机。
各大厂商也就纷纷推出各种耐摔型手机。x星球的质监局规定了手机必须经过耐摔测试,并且评定出一个耐摔指数来,之后才允许上市流通。
x星球有很多高耸入云的高塔,刚好可以用来做耐摔测试。塔的每一层高度都是一样的,与地球上稍有不同的是,他们的第一层不是地面,而是相当于我们的2楼。
如果手机从第7层扔下去没摔坏,但第8层摔坏了,则手机耐摔指数=7。
特别地,如果手机从第1层扔下去就坏了,则耐摔指数=0。
如果到了塔的最高层第n层扔没摔坏,则耐摔指数=n
为了减少测试次数,从每个厂家抽样3部手机参加测试。
某次测试的塔高为n层,如果我们总是采用最佳策略,在最坏的运气下最多需要测试多少次才能确定手机的耐摔指数呢?请填写这个最多测试次数。
*
*
* 三部手机参加测试 理解 最佳策略下的最坏运气 意思就是 三部手机都摔坏了 但是又是都摔坏的最佳的情况下 那就是次数最少的
*
* dp解决 记忆法
* 假设f(n,p)表示n层楼高时,k部手机 的最少次数
* 那么当我在k层楼扔下一部手机
* 那么就有两种可能
* 1:手机没坏 那么就可以确保1到k楼都是不需要再测的了 那么就需要测(k+1,n)楼 手机还剩p部
* 2:手机坏了 那么k+1到n就不需要测了 需要继续测(1,k-1)楼 手机还剩p-1部
* 仔细看 扔了k楼后 剩下的(k+1,n)或者(1,k-1)和手机剩余部数, 其实就是问题的子问题
* 那么 f(n,k)就等于 f(n-k,p)+1 或者是 f(k-1,p-1)+1
* 但问题k我们不知道 所以需要遍历k的取值
* 要最佳策略 那么我就应该取k是最合适的楼层 测出的次数是最小的,但是又是最坏情况下 那么就是取两种可能中最大的次数
*
* 要注意的是每次取本次K中的max与上一次k得到的dp[i][j]相比 取最小的 因为是最佳策略
* 所以一开始要有个非常大的值与 第一次K的比较 数组初始化都是0
* Integer.MAX_VALUE
*/
public class Main1262 {
public static void main(String[] args) {
Scanner cin = new Scanner(System.in);
while(cin.hasNext()) {
int n = cin.nextInt();
int[][] dp = new int[n+1][4];
for(int i=1;i<n;i++)
dp[i][1] = i;
for(int p=2;p<4;p++) {
for(int i=1;i<=n;i++) {
dp[i][p] = Integer.MAX_VALUE;
for(int k=1;k<=i;k++) {
dp[i][p] = Math.min(dp[i][p],1+Math.max(dp[i-k][p], dp[k-1][p-1]));
}
}
}
System.out.println(dp[n][3]);
}
}
}