卧薪尝胆,厚积薄发。
POJ Challenge 消失之物
Date: Fri Oct 19 07:34:24 CST 2018
In Category:
NoCategory
Description:
有
$ N $
个物品,每个物品有体积,设
$c[i][j]$
为除去第
$i$
个物品之外的
$n-1$
个物品放
$j$
的容积的方案数,求
$c[i][j]$
。
$1\leqslant n,m\leqslant 20000$
Solution:
首先先求出
$f[j]$
,表示可以用
$n$
个物品放
$j$
的容积的方案数,这个只要
$01$
背包就可以了。
求
$c[i][j]$
的时候分类讨论,
$j<v[i]$
时,
$c[i][j]=f[j]$
,
$j\geqslant v[i]$
时,应该从没有限制的方案数中减去包含第
$i$
个的方案数,没有限制的就是
$f[j]$
,包含第
$i$
个就先强制选上第
$i$
个,剩余的就变成用其他
$n-1$
个物品填满
$j-v[i]$
的体积,这个就是
$c[i][j-v[i]]$
,所以就可以在
$O(NM)$
的时间复杂度内计算出来了。
Code:
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cctype>
#include<cstring>
using namespace std;
int n,m;
#define MAXN 2010
int f[MAXN];
int v[MAXN];
int c[MAXN][MAXN];
int main()
{
scanf("%d%d",&n,&m);
for(int i = 1;i <= n;++i)scanf("%d",&v[i]);
f[0] = 1;
for(int i = 1;i <= n;++i)
for(int j = m;j >= v[i];--j)
f[j] = (f[j] + f[j - v[i]]) % 10;
for(int i = 1;i <= n;++i)
{
for(int j = 0;j <= m;++j)
{
if(j < v[i])c[i][j] = f[j];
else c[i][j] = (f[j] - c[i][j - v[i]] + 10) % 10;
}
}
for(int i = 1;i <= n;++i)
{
for(int j = 1;j <= m;++j)
{
putchar(c[i][j] + '0');
}
puts("");
}
return 0;
}
In tag:
DP-背包
Copyright © 2020
wjh15101051
ღゝ◡╹)ノ♡