Ural 1223.Chernobyl’ Eagle on a Roof

来源:互联网 发布:计算机语言翻译软件 编辑:程序博客网 时间:2024/05/21 18:29

  题目的大意是有x(1<=x<=1000)个强度相同的蛋,有一座有y(1<=y<=1000)层的楼,蛋的强度为E(0<=E<=y),在i层把蛋扔下楼,若E<i则蛋碎一地,否则不会碎,可以继续用于实验。要求求解在最坏的情况下至少需要扔多少次才能确定蛋的强度。

 很裸的动归题,最容易想的就是开个二维数组,dp[x][y]表示用x个蛋在y层楼高的楼测试最坏情况下至少需要

dp[x][y]次测试。状态转移是如果在第i层扔蛋,碎的话说明E<i,变成求1+dp[x-1][i-1],否则E>=i,变成求

1+dp[x][y-i],由于是最坏情况,所以取两者的较大者作为在第i层扔蛋所需的测试总数,由于要求最小值,那就对每层都做同样的计算取最小者。这里使用记忆化搜索会比较简便。

 但是第一个案例就TLE了,原因是这是O(n^3)的算法,1000的3次方肯定超时。然后这时发现,因为假设情况最坏,所以每次测试缩小的范围都会尽可能小,那么要最快测试完就是二分地测试,1000至多需要10次就能结束,所以当蛋数目超过10跟只有10个的结果是一样的,所以开的dp数组可以缩小至11*1001,在记忆化搜索中当y>10时返回y=10的结果即可。这就把复杂度压缩到O(n^2).

#include <iostream>#include <cstring>using namespace std;int dp[15][1001];int d(int a, int b){if (a > 11)return d(11, b);if (dp[a][b] != -1)return dp[a][b];if (a == 1)return dp[a][b] = b;if (b == 0)return dp[a][b] = 0;for (int i = 1;i <= b;i++){int temp = 1 + d(a - 1, i - 1) > 1 + d(a, b - i) ? 1 + d(a - 1, i - 1) : 1 + d(a, b - i);if (dp[a][b] == -1 || dp[a][b] > temp)dp[a][b] = temp;}return dp[a][b];}int main(){memset(dp, -1, sizeof(dp));while (1){int a, b;cin >> a >> b;if (a == 0 && b == 0)break;cout << d(a, b) << endl;}}


0 0
原创粉丝点击