Dollar Dayz POJ 3181(完全背包)

原题

题目链接

题目分析

完全背包题,不过需要状压和处理大数,首先定义dp[i][j]为用前i种货币(从1-k),凑出j价格的方案数,dp初始化为0,然后更新有两个方向,第一种显然dp[i][j]+=dp[i-1][j],第二种dp[i][j]+=dp[i-1][j-i]+dp[i-1][j-2i]+dp[i-1][j-3i]....直到j-ki<0为止,第二种更新方向想一下可以优化成dp[i][j]+=dp[i][j-i],这里因为i只有(i,i-1),所以可以状压,由dp更新方向知可直接压成第二为维,j的更新方向从小到大即可.这里的大数不大,可以把两个longlong构成一个大数,也就是一个longlong放后17位数,另一个放前17位数,具体操作可以参考代码.

代码

 1 #include <iostream>
 2 #include <algorithm>
 3 #include <utility>
 4 #include <cstdio>
 5 #include <cmath>
 6 #include <cstring>
 7 #include <string>
 8 #include <vector>
 9 #include <stack>
10 #include <queue>
11 #include <map>
12 #include <set>
13 
14 using namespace std;
15 typedef long long LL;
16 const int INF_INT=0x3f3f3f3f;
17 const LL INF_LL=0x3f3f3f3f3f3f3f3f;
18 
19 const LL limit=1e17;
20 LL dp[2000][2];
21 
22 int main()
23 {
24 //    freopen("black.in","r",stdin);
25 //    freopen("black.out","w",stdout);
26     int n,k;
27     cin>>n>>k;
28     dp[0][0]=1;
29     for(int i=1;i<=k;i++)
30     {
31         for(int j=0;j<=n;j++)
32         if(j-i>=0)
33         {
34             dp[j][0]+=dp[j-i][0];
35             dp[j][1]+=dp[j-i][1];
36             dp[j][1]+=dp[j][0]/limit;
37             dp[j][0]=dp[j][0]%limit;
38         }
39    /*     for(int j=0;j<=n;j++)
40         {
41             printf("dp[%d][%d]=",i,j);
42             if(dp[j][1]) printf("%lld",dp[j][1]);
43             printf("%lld\n",dp[j][0]);
44         }*/
45     }
46     if(dp[n][1]) printf("%lld",dp[n][1]);
47     printf("%lld\n",dp[n][0]);
48     return 0;
49 }

 

posted @ 2019-08-25 14:25  VBL  阅读(107)  评论(0编辑  收藏  举报