NKOJ2321 东方project

  背包dp问题的变体,每一关看成一个背包,用的炸弹数看成重量,通关概率看成物品总价值,然后本关与之前所有关卡用的炸弹数最优分配用分类讨论。注意到若用100个炸弹则必定通关,那么枚举100个或剪枝都行。时间复杂度为o(100nm),最多正好是十的八次方。

 

 1 #include<iostream>
 2 #include<vector>
 3 #include<cstdio>
 4 using namespace std;
 5 double dp[1005][1001];//dp[a][b]代表通a关用b个炸弹的最大通过概率
 6 
 7 struct level {
 8     int k, b;
 9 };
10 
11 double min(double a, double b)
12 {
13     return a < b ? a : b;
14 }
15 
16 double max(double a, double b)
17 {
18     return a > b ? a : b;
19 }
20 
21 double mayPoint(int k, int b, int x)
22 {
23     return min(1, double(k*x + b) / (double)100);
24 }
25 
26 
27 int main()
28 {
29     int n, m;
30     scanf("%d%d",&n,&m);
31     vector<level> levels(n+1);
32     for (int i = 1; i <= n; ++i)
33     {
34         int k, b;
35         scanf("%d%d", &k, &b);
36         levels[i].b = b;
37         levels[i].k = k;
38     }
39     for (int i = 0; i <= m; ++i)
40     {
41         dp[0][i] = 1;
42     }
43     for (int i = 1; i <= n; ++i)
44     {
45         for (int nb = 0; nb <= m; ++nb)
46         {
47             for (int b = nb; b <= m; ++b)
48             {
49                 dp[i][b] = max(dp[i][b], dp[i - 1][b - nb] * mayPoint(levels[i].k, levels[i].b, nb));
50             }
51             if (mayPoint(levels[i].k, levels[i].b, nb) >= 1)break;
52         }
53     }
54     for (int i = 0; i <= n; ++i)
55     {
56         for (int j = 0; j <= m; ++j)
57         {
58             cout << dp[i][j] << "\t";
59         }
60         cout << endl;
61     }
62     printf("%lf\n", dp[n][m]);
63     
64 }
View Code

(卡了一个小时最后还没做出来,菜swl)

posted @ 2017-09-14 14:32  Al_X  阅读(268)  评论(0编辑  收藏  举报