1. 程式人生 > >NKOJ2321 東方project

NKOJ2321 東方project

++ one 背包 分類討論 概率 背包dp std double mes

  背包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)

NKOJ2321 東方project