Codechef:Little Elephant and Boxes/LEBOXES(折半搜索)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_35649707/article/details/83104820

传送门

题解:
预处理一个 f i , j f_{i,j} 表示有 i i 个钻石,购买了 j j 个物品所需要的最小费用,然后就可以愉快的折半了。

#include <bits/stdc++.h>
using namespace std;
typedef pair <int,double> pid;
const int RLEN=1<<18|1;
inline char nc() {
	static char ibuf[RLEN],*ib,*ob;
	(ib==ob) && (ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
	return (ib==ob) ? -1 : *ib++;
}
inline int rd() {
	char ch=nc(); int i=0,f=1;
	while(!isdigit(ch)) {if(ch=='-')f=-1; ch=nc();}
	while(isdigit(ch)) {i=(i<<1)+(i<<3)+ch-'0'; ch=nc();}
	return i*f;
}

const int N=32, inf=1e9;
int n,m,mid,f[N][N],v[N],c[N],d[N]; double p[N],ans;
vector <pid> q[N];
vector <double> s[N];
inline void dfs1(int i,int nn,int c1,int c2,double t) {
	if(i==nn+1) {q[c2].push_back(pid(c1,t)); return;}
	dfs1(i+1,nn,c1,c2+1,t*(1-p[i]));
	dfs1(i+1,nn,c1+v[i],c2,t*p[i]);
}
inline void dfs2(int i,int nn,int c1,int c2,double t) {
	if(i==nn+1) {
		for(int j=0;j<=mid;j++) {
			int lst=0;
			for(int k=0;k<=m;k++) {
				int p=lower_bound(q[j].begin(),q[j].end(),(k==m) ? pid(inf,inf) : pid(f[c2+j][k+1]-c1,0))-q[j].begin()-1;
				if(~p) ans+=(s[j][p]-(lst ? s[j][lst-1] : 0))*t*k; lst=p+1;
				if(lst==q[j].size()) break;
			}
		} return;
	}
	dfs2(i+1,nn,c1,c2+1,t*(1-p[i]));
	dfs2(i+1,nn,c1+v[i],c2,t*p[i]);
}
inline void solve() {
	n=rd(), m=rd(); ans=0;
	for(int i=1;i<=n;i++) v[i]=rd(), p[i]=(double)rd()/100;
	for(int i=1;i<=m;i++) c[i]=rd(), d[i]=rd();
	for(int i=0;i<=n;i++) for(int j=0;j<=m;j++) f[i][j]=inf;
	f[0][0]=0;
	for(int i=1;i<=m;i++)
		for(int j=n;j>=d[i];j--)
			for(int k=i;k>=1;k--)
				f[j][k]=min(f[j][k],f[j-d[i]][k-1]+c[i]);
	for(int i=1;i<=n;i++) 
		for(int j=0;j<=m;j++)
			f[i][j]=min(f[i][j],f[i-1][j]);
	mid=min(18,n);
	for(int i=1;i<=mid;i++) q[i].clear();	for(int i=1;i<=mid;i++) q[i].clear();
	dfs1(1,mid,0,0,1);
	for(int i=0;i<=mid;i++) {
		sort(q[i].begin(),q[i].end());
		s[i].assign(q[i].size(),0);
		for(int j=0;j<q[i].size();j++) s[i][j]=q[i][j].second+(j?s[i][j-1]:0);
	}
	dfs2(mid+1,n,0,0,1);
	printf("%.4f\n",ans);
}
int main() {
	for(int T=rd();T;T--) solve();
}

猜你喜欢

转载自blog.csdn.net/qq_35649707/article/details/83104820