背包dp(完全)
http://poj.org/problem?id=3181
高精+背包
完全背包求方案数则只需dp[ j ] + = dp[ j - w[ i ] ]即可;任意一种背包方案计算都只需将max变为+;
这道题要注意,求方案数一般有很多,不mod,就自己看看数据是否超内存;
dp[ i ]存放前18位;dp[ i ]存放后18位;
对于前18位 dp[ j ]= dp[ j ] + dp [ j-w[ i ] ] + ( dp1[ j ]+dp1[ j-w[ i ] ) / inf
前18位相加,在加上后18位相加时产生的进位;
1 #include<iostream> 2 #include<string.h> 3 using namespace std; 4 #define int long long 5 const int maxn=1100; 6 __int64 inf=1; 7 int dp[maxn],dp1[maxn]; 8 signed main() 9 { 10 int n,k; 11 cin>>n>>k; 12 memset(dp,0,sizeof(dp)); 13 memset(dp1,0,sizeof(dp1)); 14 for (int i=0; i<18; i++) inf *= 10; 15 dp1[0]=1; 16 for(int i=1;i<=k;i++) 17 { 18 for(int j=i;j<=n;j++) 19 { 20 dp[j]=dp[j]+dp[j-i]+(dp1[j]+dp1[j-i])/inf; 21 dp1[j]=(dp1[j]+dp1[j-i])%inf; 22 } 23 } 24 if(dp[n]) cout<<dp[n]; 25 cout<<dp1[n]<<endl; 26 }
完全背包模板题;
适合深刻理解装满状态;
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int inf=0x3f3f3f3f; 4 const int maxn=10010; 5 int dp[maxn],n,m,e,f,val[maxn],w[maxn]; 6 signed main() 7 { 8 cin>>n; 9 while(n--) 10 { 11 scanf("%d %d",&e,&f); 12 scanf("%d",&m); 13 for(int i=1;i<=m;i++) 14 { 15 scanf("%d %d",&val[i],&w[i]); 16 } 17 memset(dp,inf,sizeof(dp)); 18 dp[0]=0; 19 for(int i=1;i<=m;i++) 20 { 21 for(int j=w[i];j<=f-e;j++) 22 { 23 dp[j]=min(dp[j],dp[j-w[i]]+val[i]); 24 } 25 } 26 if(dp[f-e]==inf) printf("This is impossible.\n"); 27 else printf("The minimum amount of money in the piggy-bank is %d.\n",dp[f-e]); 28 } 29 }