ACM-ICPC 2018 焦作赛区网络预赛 K. Transport Ship(DP)

题目链接:https://nanti.jisuanke.com/t/31720

题意:有n种飞船,每种飞船有(1 << c)- 1  艘,容量为 k[i] ,q 次询问,每次询问选若干艘飞船使得容量为 s 的方案数。

题解:预处理出全部情况。dp[ i ][ j ]表示选前 i 个物品凑出容量为 k 的方案数,转移的时候可注意到dp[ i ][ j ] = sigma(dp[i - 1][j - x * v ]),然后减掉不合法的情况(x > ( (1 << c) - 1) )。详见代码~

 

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 #define ll long long
 4 #define LL __int128
 5 #define ull unsigned long long
 6 #define mst(a,b) memset((a),(b),sizeof(a))
 7 #define mp(a,b) make_pair(a,b)
 8 #define fi first
 9 #define se second
10 #define pi acos(-1)
11 #define pii pair<int,int>
12 #define pb push_back
13 const int INF = 0x3f3f3f3f;
14 const double eps = 1e-6;
15 const int MAXN = 1e4 + 10;
16 const int MAXM = 1e6 + 10;
17 const ll mod = 1e9 + 7;
18 
19 ll dp[22][MAXN];
20 
21 int main()
22 {
23 #ifdef local
24     freopen("data.txt", "r", stdin);
25 //    freopen("data.txt", "w", stdout);
26 #endif
27     int t;
28     scanf("%d",&t);
29     while(t--) {
30         int n,q;
31         scanf("%d%d",&n,&q);
32         mst(dp, 0);
33         dp[0][0] = 1;
34         for(int i = 1; i <= n; i++) {
35             int c,v;
36             scanf("%d%d",&v,&c);
37             c = (1 << c) * v;
38             for(int j = 0; j < v; j++) dp[i][j] = dp[i - 1][j];
39             for(int j = v; j <= 10000; j++) {
40                 dp[i - 1][j] += dp[i - 1][j - v];
41                 if(dp[i - 1][j] >= mod) dp[i - 1][j] -= mod;
42                 dp[i][j] = dp[i - 1][j];
43                 if(j >= c) {
44                     dp[i][j] -= dp[i - 1][j - c];
45                     if(dp[i][j] < 0) dp[i][j] += mod;
46                 }
47             }
48         }
49         while(q--) {
50             int s;
51             scanf("%d",&s);
52             printf("%lld\n",dp[n][s]);
53         }
54     }
55     return 0;
56 }

 

posted on 2018-09-15 23:36  scau_lok  阅读(272)  评论(0编辑  收藏  举报

导航