CF1458B Glass Half Spilled
Posted Jozky86
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CF1458B Glass Half Spilled相关的知识,希望对你有一定的参考价值。
题意:
有n杯水,第i杯有容积
a
i
a_{i}
ai单位,初始时装有
b
i
b_{i}
bi单位的水
现在你可以进行若干次操作,每次选择一杯水的一定水量并倒到另一杯水中,但是因为这些杯子形状非常奇怪,因此每倒一次水,倒的水会有一半洒在地上.
求出对于所有整数p满足
1
<
=
p
<
=
n
1<=p<=n
1<=p<=n,求出进行若干次操作后选取p个杯子能获得水单位数量的最大值
题解:
每次倒水都会有损失,那么倒水的过程肯定不能出现同样的水来回倒,这样必不优。因此我们就直接选中p个杯子,让后将其他杯子里的水都倒进来。设选出的k个杯子的a值和为A且b值和为B,所有杯子的b值和为sumb。可以得到答案min{A,(sumb-B) * 0.5+B}=min{A,sumb * 0.5+B * 0.5}
现在我们就要求出对于每个A所对应的尽可能大的B(因为A是给出的,B不好求)
我们把A看作容积,把B看作价值,这不就是01背包,但本题A的容积不是固定的
A表示容积,而最多就100个杯子,每个杯子容积最大是100,也就是说A最大才10000,所以我们完全可以直接枚举容积
因为题目问k个杯子的情况,所以我们还需要一维来记录所选杯子数量
设dp[i][j]][k]:前i个杯子选了j个,且容积为k的最大价值(最大盛水容量)
我们可以通过滚动数组优化第一维
时间复杂度为
O
(
n
4
)
O(n^4)
O(n4)
代码:
#include <bits/stdc++.h>
#include <unordered_map>
#define debug(a, b) printf("%s = %d\\n", a, b);
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> PII;
clock_t startTime, endTime;
//Fe~Jozky
const ll INF_ll= 1e18;
const int INF_int= 0x3f3f3f3f;
void read(){};
template <typename _Tp, typename... _Tps> void read(_Tp& x, _Tps&... Ar)
{
x= 0;
char c= getchar();
bool flag= 0;
while (c < '0' || c > '9')
flag|= (c == '-'), c= getchar();
while (c >= '0' && c <= '9')
x= (x << 3) + (x << 1) + (c ^ 48), c= getchar();
if (flag)
x= -x;
read(Ar...);
}
template <typename T> inline void write(T x)
{
if (x < 0) {
x= ~(x - 1);
putchar('-');
}
if (x > 9)
write(x / 10);
putchar(x % 10 + '0');
}
void rd_test()
{
#ifdef ONLINE_JUDGE
#else
startTime = clock ();
freopen("data.in", "r", stdin);
#endif
}
void Time_test()
{
#ifdef ONLINE_JUDGE
#else
endTime= clock();
printf("\\nRun Time:%lfs\\n", (double)(endTime - startTime) / CLOCKS_PER_SEC);
#endif
}
const int maxn=300;
struct node{
int a,b;
}w[maxn];
int dp[102][10020];
int main()
{
//rd_test();
int n;
read(n);
int sum=0;
for(int i=1;i<=n;i++){
cin>>w[i].a>>w[i].b;
sum+=w[i].b;
}
memset(dp,-INF_int,sizeof dp);
dp[0][0]=0;
for(int i=1;i<=n;i++){
for(int j=i;j>=1;j--){
for(int k=10000;k>=w[i].a;k--){
dp[j][k]=max(dp[j][k],dp[j-1][k-w[i].a]+w[i].b);
}
}
}
for(int i=1;i<=n;i++){
double ans=0;
for(int k=0;k<=10000;k++){
ans=max(ans,1.0*min(1.0*k,0.5*sum+0.5*dp[i][k]));
}
printf("%.9lf ",ans);
// cout<<ans<<endl;
}
return 0;
//Time_test();
}
以上是关于CF1458B Glass Half Spilled的主要内容,如果未能解决你的问题,请参考以下文章