“蔚来杯“2022牛客暑期多校训练营4 A题: Task Computing

A题: Task Computing

原题链接:https://ac.nowcoder.com/acm/contest/33189/A

题目大意

n n n 台云服务器,第 i i i 台具有计算效率 w i w_i wi 和传输效率 p i p_i pi
对于一个计算任务,需要恰好在 m m m 台服务器上计算,设这 m m m 台服务器依次为 a 1 , a 2 , . . . , a m a_1,a_2,...,a_m a1,a2,...,am 则最终计算效率为
∑ i = 1 m w a i ∏ j = 0 i = 1 p a j \sum\limits_{i=1}^mw_{a_i}\prod\limits_{j=0}^{i=1}p_{a_j} i=1mwaij=0i=1paj
初始 a 0 = 0 , p 0 = 1 a_0=0,p_0=1 a0=0,p0=1
求这 m m m 台服务器在最优排序下的最大计算效率。

题解

考虑在最优解中相邻的两台云服务器 a k , a k + 1 a_k,a_{k+1} ak,ak+1 ,设 a k = x , a k + 1 = y a_k=x,a_{k+1}=y ak=x,ak+1=y (即 w a k = w x , p a k + 1 = p y w_{a_k}=w_x,p_{a_{k+1}}=p_y wak=wx,pak+1=py )。
则显然此时的总贡献为
W = ∑ i = 1 k − 1 w a i ∏ j = 0 i − 1 p a j + w x ∏ j = 0 k − 1 p a j + w y p x ∏ j = 0 k − 1 p a j + ∑ i = k + 2 m w a i ∏ j = 0 i − 1 p a j W=\sum\limits_{i=1}^{k-1}w_{a_i}\prod\limits_{j=0}^{i-1}p_{a_j}+w_x\prod\limits_{j=0}^{k-1}p_{a_j}+w_yp_x\prod\limits_{j=0}^{k-1}p_{a_j}+\sum\limits_{i=k+2}^mw_{a_i}\prod\limits_{j=0}^{i-1}p_{a_j} W=i=1k1waij=0i1paj+wxj=0k1paj+wypxj=0k1paj+i=k+2mwaij=0i1paj

(第三项中 w y p x ∏ j = 0 k − 1 p a j = w y ∏ j = 0 k p a j w_yp_x\prod\limits_{j=0}^{k-1}p_{a_j}=w_ y\prod\limits_{j=0}^{k}p_{a_j} wypxj=0k1paj=wyj=0kpaj )
若我们交换这两台云服务器,即令 a k = y , a k + 1 = x a_k=y,a_{k+1}=x ak=y,ak+1=x
则显然此时的总贡献为
W ′ = ∑ i = 1 k − 1 w a i ∏ j = 0 i − 1 p a j + w y ∏ j = 0 k − 1 p a j + w x p y ∏ j = 0 k − 1 p a j + ∑ i = k + 2 m w a i ∏ j = 0 i − 1 p a j W'=\sum\limits_{i=1}^{k-1}w_{a_i}\prod\limits_{j=0}^{i-1}p_{a_j}+w_y\prod\limits_{j=0}^{k-1}p_{a_j}+w_xp_y\prod\limits_{j=0}^{k-1}p_{a_j}+\sum\limits_{i=k+2}^mw_{a_i}\prod\limits_{j=0}^{i-1}p_{a_j} W=i=1k1waij=0i1paj+wyj=0k1paj+wxpyj=0k1paj+i=k+2mwaij=0i1paj

做差可得
W − W ′ = ( w x ∏ j = 0 k − 1 p a j + w y p x ∏ j = 0 k − 1 p a j ) − ( w y ∏ j = 0 k − 1 p a j + w x p y ∏ j = 0 k − 1 p a j ) = ∏ j = 0 k − 1 p a j ( w x + w y p x − w y − w x p y ) \begin{aligned} W-W'&=(w_x\prod\limits_{j=0}^{k-1}p_{a_j}+w_yp_x\prod\limits_{j=0}^{k-1}p_{a_j})-(w_y\prod\limits_{j=0}^{k-1}p_{a_j}+w_xp_y\prod\limits_{j=0}^{k-1}p_{a_j})\\ &=\prod\limits_{j=0}^{k-1}p_{a_j}(w_x+w_yp_x-w_y-w_xp_y) \end{aligned} WW=(wxj=0k1paj+wypxj=0k1paj)(wyj=0k1paj+wxpyj=0k1paj)=j=0k1paj(wx+wypxwywxpy)

因为在最优解中 a k = x , a k + 1 = y a_k=x,a_{k+1}=y ak=x,ak+1=y ,故 W − W ′ ≥ 0 W-W'\ge0 WW0 ,因为 ∏ j = 0 k − 1 p a j > 0 \prod\limits_{j=0}^{k-1}p_{a_j}>0 j=0k1paj>0 , 所以可得 w x + w y p x − w y − w x p y ≥ 0 w_x+w_yp_x-w_y-w_xp_y\ge0 wx+wypxwywxpy0 ,根据该公式进行排序后,最优解肯定为云服务器的一个子序列(因为排序后换位不可能使答案更优了)。


关于偏序性的证明

w x + w y p x − w y − w x p y ≥ 0 w x − w x p y ≥ w y − w y p x w x ( 1 − p y ) ≥ w y ( 1 − p x ) 1 − p y w y ≥ 1 − p x w x \begin{aligned} w_x+w_yp_x-w_y-w_xp_y&\ge0\\ w_x-w_xp_y&\ge w_y-w_yp_x\\ w_x(1-p_y)&\ge w_y(1-p_x)\\ \frac{1-p_y}{w_y}&\ge \frac{1-p_x}{w_x} \end{aligned} wx+wypxwywxpywxwxpywx(1py)wy1py0wywypxwy(1px)wx1px

该式左右两边分别只与 y , x y,x y,x 有关,显然具有传递性。


排序后,注意我们不能设状态 d p i , j dp_{i,j} dpi,j 表示前 i i i 台云服务器中选择 j j j 台的最优效率,然后大力 d p dp dp 。考虑到对于式 ∑ i = 1 m w a i ∏ j = 0 i = 1 p a j \sum\limits_{i=1}^mw_{a_i}\prod\limits_{j=0}^{i=1}p_{a_j} i=1mwaij=0i=1paj ,前面所选择的云服务器的 p p p 会对后面存在影响,因此存在后效性,不能直接 d p dp dp (同时我们也不能将 p p p 作为状态保存,复杂度不允许,而且浮点数也不方便保存)。

因此,我们设状态 d p i , j dp_{i,j} dpi,j 表示从第 i i i n n n 台云服务器中选择 m m m 台的最优效率,此时后面所选择的云服务器不会对排在前面的云服务器造成影响,无后效性,可行。
易得转移式:
d p i , j = m a x { d p i + 1 , j ( 不选择第 i 台云服务器 ) d p i + 1 , j − 1 ∗ p i + w i ( 选择第 i 台云服务器 ) dp_{i,j}=max \begin{cases} dp_{i+1,j}&(不选择第i台云服务器)\\ dp_{i+1,j-1}*p_i+w_i&(选择第i台云服务器) \end{cases} dpi,j=max{dpi+1,jdpi+1,j1pi+wi(不选择第i台云服务器)(选择第i台云服务器)

最终答案即为 d p 1 , m dp_{1,m} dp1,m

参考代码

#include<bits/stdc++.h>
using namespace std;

template<class T>inline void read(T&x){//快读
	char c,last=' ';
	while(!isdigit(c=getchar()))last=c;
	x=c^48;
	while(isdigit(c=getchar()))x=(x<<3)+(x<<1)+(c^48);
	if(last=='-')x=-x;
}

const int MAXN=1e5+5;
int n,m;
double dp[MAXN][25];
struct node{
	int w;
    double p;
}a[MAXN];
bool cmp(node a,node b){
	return (1-a.p)/a.w<(1-b.p)/b.w;//注意sort时不允许有等号
}

int main()
{
	read(n),read(m);
	for(int i=1;i<=n;++i)read(a[i].w);
	for(int i=1;i<=n;++i)cin>>a[i].p,a[i].p/=10000;
	sort(a+1,a+n+1,cmp);
	double ans=0;
	for(int i=n;i>=1;--i){
		for(int j=1;j<=min(m,n-i+1);++j){
			dp[i][j]=max(dp[i+1][j],dp[i+1][j-1]*a[i].p+a[i].w);
        }
	}
	cout<<fixed<<setprecision(12)<<dp[1][m]<<'\n';
	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值