do_while_true

一言(ヒトコト)

「题解」洛谷 P6893 [ICPC2014 WF]Buffed Buffet

对于离散的食物,\(w\) 相同的只留下美味值最大的 \(W/w\) 个,因为再多了也没用不会更优。所以一共只有 \(\sum_{i=1}^n \frac{W}{i}=\mathcal{O}(W\log n)\) 这样暴力背包复杂度就是 \(\mathcal{O}(W^2\log n)\)

然后考虑连续的怎么做。枚举离散的占了 \(w\) 的重量,那么离散的一定是先取不断吃最美味的,直到最美味的和次美味的一样好吃,这样这两个食物就可以看成一个了。加入其中两个 \(\Delta t\) 分别是 \(x,y\),稍微推推能推出新的食物的 \(\Delta t\)\(\frac{xy^2+x^2y}{(x+y)^2}\)

所以总复杂度就是 \(\mathcal{O}(W^2\log n+Wn)\)

#include<cstdio>
#include<vector>
#include<queue>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<ctime>
#include<random>
#include<assert.h>
#define pb emplace_back
#define mp make_pair
#define fi first
#define se second
#define dbg(x) cerr<<"In Line "<< __LINE__<<" the "<<#x<<" = "<<x<<'\n';
#define dpi(x,y) cerr<<"In Line "<<__LINE__<<" the "<<#x<<" = "<<x<<" ; "<<"the "<<#y<<" = "<<y<<'\n';
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef double ld;
typedef pair<int,int>pii;
typedef pair<ld,ld>pdd;
typedef pair<ll,int>pli;
typedef pair<ll,ll>pll;
typedef pair<int,ll>pil;
typedef vector<int>vi;
typedef vector<ll>vll;
typedef vector<pii>vpii;
typedef vector<pil>vpil;
template<typename T>T cmax(T &x, T y){return x=x>y?x:y;}
template<typename T>T cmin(T &x, T y){return x=x<y?x:y;}
template<typename T>
T &read(T &r){
	r=0;bool w=0;char ch=getchar();
	while(ch<'0'||ch>'9')w=ch=='-'?1:0,ch=getchar();
	while(ch>='0'&&ch<='9')r=r*10+(ch^48),ch=getchar();
	return r=w?-r:r;
}
template<typename T1,typename... T2>
void read(T1 &x,T2& ...y){read(x);read(y...);}
const int mod=998244353;
inline void cadd(int &x,int y){x=(x+y>=mod)?(x+y-mod):(x+y);}
inline void cdel(int &x,int y){x=(x-y<0)?(x-y+mod):(x-y);}
inline int add(int x,int y){return (x+y>=mod)?(x+y-mod):(x+y);}
inline int del(int x,int y){return (x-y<0)?(x-y+mod):(x-y);}
int qpow(int x,int y){
	int s=1;
	while(y){
		if(y&1)s=1ll*s*x%mod;
		x=1ll*x*x%mod;
		y>>=1;
	}
	return s;
}
const int N=10010;
const ll inf=0x3f3f3f3f3f3f3f3f;
int n,m,W;
pdd lx[N],b[N];
vpii vec[N],ls;
ll f[N];
ld calc(pdd x,ld y){
	return x.fi*y-0.5*x.se*y*y;
}
signed main(){
	#ifdef do_while_true
//		assert(freopen("data.in","r",stdin));
//		assert(freopen("data.out","w",stdout));
	#endif
	read(n,W);
	for(int i=1;i<=W;i++)f[i]=-inf;
	for(int i=1;i<=n;i++){
		int w,t,dt;
		char c=getchar();while(c<'A'||c>'Z')c=getchar();
		if(c=='D'){
			read(w,t,dt);
			vec[w].pb(mp(t,dt));
		}
		else{
			read(t,dt);
			lx[++m]=mp(t,dt);
		}
	}
	sort(lx+1,lx+m+1,[](const pdd &x,const pdd &y){return x>y;});
	for(int o=1;o<=W;o++)if(vec[o].size()){
		vi a;
		for(auto i:vec[o])
			for(int j=1;j<=W/o;j++)
				a.pb(i.fi-(j-1)*i.se);
		nth_element(a.begin(),a.begin()+W/o,a.end(),[](const int &x,const int &y){return x>y;});
		for(int i=0;i<W/o;i++)
			for(int j=W;j>=o;j--)
				if(f[j-o]!=-inf)
					cmax(f[j],f[j-o]+a[i]);
	}
	if(m==0){
		if(f[W]==-inf)puts("impossible");
		else cout << f[W] << '\n';
		return 0;
	}
	ld ans;
	for(int o=0;o<=W;o++){
		for(int i=1;i<=m;i++)b[i]=lx[i];
		ld sum=f[o],rem=W-o;
		for(int i=1;i<=m;i++){
			if(i<m){
				ld delta=(b[i].fi-b[i+1].fi)/b[i].se;
				if(rem>delta){
					sum+=calc(b[i],delta);
					rem-=delta;
					ld x=b[i].se,y=b[i+1].se;
					b[i+1].se=(x*y*y+x*x*y)/((x+y)*(x+y));
				}
				else{
					sum+=calc(b[i],rem);
					break;
				}
			}
			else sum+=calc(b[i],rem);
		}
		if(o==0)ans=sum;
		else cmax(ans,sum);
	}
	printf("%.10lf\n",ans);
    #ifdef do_while_true
		cerr<<'\n'<<"Time:"<<1.0*clock()/CLOCKS_PER_SEC*1000<<" ms"<<'\n';
	#endif
	return 0;
}
posted @ 2023-02-07 15:06  do_while_true  阅读(48)  评论(0编辑  收藏  举报