Description
有 (n) 根柱子,可以按任意顺序放置形成一个二维图形,一个二维图形可以用来接若干单位面积的水。给定 (n le 500) 根柱子的高度 (h_i le 50),求所有可能的水量。
Solution
解法比较神仙
首先将所有柱子从高到低排序,很显然我们只会从高到低填入(当然也可能放弃一些柱子),较短的那些柱子如果没用完也可以不考虑
维护某个状态能接住的水量其实非常困难,我们考虑维护水量和柱子高度的总和
设 (f[i][j]) 表示从左到右填了 (i) 个空位(注意有些空位可能暂时不放柱子),是否能拼成 (j) 体积的水量和柱子高度的总和
考虑从大到小枚举所有柱子 (i),再从左向右枚举所有空位 (j),从 ((i-1,j-1)) 和 ((i,j-1)) 转移过来
用 std::bitset
优化即可
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 505;
const int M = 30005;
bitset <M> f[N],ans;
int n,a[N],sum;
signed main()
{
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1;i<=n;i++) sum+=a[i];
sort(a+1,a+n+1,greater<int>());
f[1][a[1]]=1;
for(int i=2;i<=n;i++)
{
for(int j=i;j<=n;j++) f[j]|=f[j-1]<<a[i];
ans|=f[n];
}
for(int i=sum;i<M;i++) if(ans[i]) cout<<i-sum<<" ";
system("pause");
}