首页 > 其他 > 详细

P4141 消失之物

时间:2019-08-15 19:00:38      阅读:82      评论:0      收藏:0      [点我收藏+]

P4141 消失之物

 

ftiasch 有 个物品体积分别是 W1, W2, ..., WN。 由于她的疏忽第 个物
品丢失了。 “要使用剩下的 N - 1 物品装满容积为 的背包,有几种方法
呢?” -- 这是经典的问题了。
?她把答案记为 Count(i, x) ,想要得到所有1 <= i <= N, 1 <= x <= M的 Count(i,
x) 表格。
N,M<=3000

 

 

 

题解

 

?f[x]表示全部物品都可用恰好装满x体积时的方案数,可以用01背包算法
求出。这是总方案数。
?然后考虑不选某物品的情况。
?g[x]为不选当前物品恰好装满x体积时的方案数。

 

f[i]加进去当前物品,  g[i]不加

 

f[i]=f[i]+f[i-w[i]]

 

f[i]=g[i]+g[i-w[i]]

 

g[i]=f[i]-g[i-w[i]]

 

?x小于w[i]时, i物品一定不会被选上 g[i]=f[i]
?x大于等于w[i]时, i物品可能会被选上,直接求不选的情况比较困难。
?总方案数及f[x],不选的方案数可以想为先不选i再最后把i选上,g[x-w[i]]
?所以g[x]=f[x]-g[x-w[i]], x从小到大枚举计算g即可。
?每次都是线性复杂度,一共n次计算,总复杂度是O(n*m) 

 

另两种理解方式
1:也可以用生成函数来理解。
2:直接考虑程序代码也可以很简单的理解。 

 

 

 

 

上面有些晦涩难懂,下面看一个仍然晦涩难懂的描述

设 f[ j ][ 0 ] 为体积为 j ,第 i 个物品可以选上的时候,体积为 j 的最大方案数

设 f[ j ][ 1 ] 为体积为 j ,第 i 个物品没选的时候,体积为 j 的最大方案数

 

假设没有物品消失,那么这就相当于一个01背包问题,f[ x ][ 0 ] 之间的转移

如果有物品消失的话,就相当于在原来的方案数上减去它

     对于物品 i ,如果当前的体积可以放进去,那么它就由 选中的方案 - 没选中的方案,因为之前可能选上了 i (QAQ太艰难了)

     对于物品 i ,如果当前的体积不能放进去,那么直接由 f[ x ][ 0 ] 转移过来,因为在原来的方案里一定是没有选中它的

 

代码

#include<bits/stdc++.h>

using namespace std;

inline int read()
{
    int ans=0;
    char last= ,ch=getchar();
    while(ch<0||ch>9) last=ch,ch=getchar();
    while(ch>=0&&ch<=9) ans=ans*10+ch-0,ch=getchar();
    if(last==-) ans=-ans;
    return ans;
}

const int maxn=2005;
int n,m;
int w[maxn];
int f[maxn][2];

int main()
{
    n=read();m=read();
    for(int i=1;i<=n;i++) w[i]=read(); 
    f[0][0]=f[0][1]=1;
for(int i=1;i<=n;i++) for(int j=m;j>=w[i];j--) f[j][0]+=f[j-w[i]][0],f[j][0]%=10;
for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) { if(j>=w[i]) f[j][1]=(f[j][0]-f[j-w[i]][1]+10)%10; else f[j][1]=f[j][0]; f[j][1]=f[j][1]%10; printf("%d",f[j][1]); } printf("\n"); } return 0; }

 

P4141 消失之物

原文:https://www.cnblogs.com/xiaoyezi-wink/p/11359206.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!