首页 > 其他分享 >KRUMPIRKO 土豆

KRUMPIRKO 土豆

时间:2022-10-20 15:48:42浏览次数:70  
标签:le int 样例 times 土豆 KRUMPIRKO dp

[COCI2015-2016#6] KRUMPIRKO

题目描述

\(\text{Mr. Potato}\) 开了两家新店卖土豆。他买了 \(N\) 袋土豆,其中第 \(i\) 袋价值为 \(c_i\),袋里有 \(a_i\) 个土豆。他打算把这 \(N\) 袋土豆整袋整袋地分在两个店里。

在每家店中,土豆的平均价格等于这家店里所有袋的土豆的总价比上土豆的个数。(注意是个数而不是袋数!)

设 \(P_1\) 为第一家店的土豆平均价格,\(P_2\) 为第二家店的土豆平均价格。\(\text{Mr. Potato}\) 希望在至少有一家店里土豆袋数正好等于 \(L\) 袋的情况下,最小化 \(P_1\times P_2\) 的值。

输入格式

第一行包含两个整数 \(N\) 和 \(L\)。

第二行包含 \(N\) 个整数 \(a_i\)。

第三行包含 \(N\) 个整数 \(c_i\)。

输出格式

第一行输出一个浮点数,为 \(P_1\times P_2\) 的最小值,保留到小数点后三位。

样例 #1

样例输入 #1

3 1
3 2 1
1 2 3

样例输出 #1

0.556

样例 #2

样例输入 #2

3 2
2 2 2
3 3 3

样例输出 #2

2.250

提示

【数据范围】

对于 \(30\%\) 的数据,\(2\le N\le 20\)。

对于 \(100\%\) 的数据,\(2\le N\le 100\),\(1\le L< N\),\(1\le a_i\le 100\),\(1\le c_i\le 10^6\),\(\sum\limits_{i=1}^{N} a_i\le 500\)。

【题目来源】

题目译自 COCI 2015-2016 CONTEST #6 T5 KRUMPIRKO

本题分值按 COCI 原题设置,满分 \(140\)

分析

前三十分很好想 \(2^n\) 枚举所有情况即可

正解

\(DP\)
题目要求\(P1\times P2=\frac{x}{y}\times\frac{\sum X-x}{\sum Y-y}\)

其中 \(x\) 表示价格,\(y\) 表示个数

将 \(\sum X\) 与 \(\sum Y\) 看做常数 \(k1\ k2\)

\(P1\times P2=\frac{k_1x-x^2}{k_2y-y^2}\)

这东西不好维护,但是他的分子分母很好搞

就是一个二次函数

那我们分开枚举 \(x\) 的同时,计算 分母 不就好了

为什么说枚举 \(x\) 呢

因为 \(x\) 在二次函数上,二次系数为负,开口朝下,最小值取值有两个

因为两个最小值取值,且一个尽可能的大,另一个尽可能小,就维护一个 \(x\) 的最大最小值

定义 \(dp[i][j][k]\) 为前 \(i\) 袋中选了 \(j\) 袋共 \(k\) 个土豆

很容易写出 \(dp[i][j][k]=(dp[i-1][j][k]\ ,\ dp[i-1][j-1][k-a[i]]+c[i])\)

最后答案枚举 \(k\) 即可

\(Ac\ code\)

#include<bits/stdc++.h>
#define N 110
#define int long long
using namespace std;
int n,L,a[N],c[N];
int suma,sumc;
int dp_n[2][N][5*N];
int dp_x[2][N][5*N];
double  ans;
template<typename T>void read(T &x)
{
	x=0;char c=getchar();T neg=0;
	while(!isdigit(c))neg|=!(c^'-'),c=getchar();
	while(isdigit(c))x=(x<<3)+(x<<1)+(c^48),c=getchar();
	if(neg)x=(~x)+1;
}//快读 
template<typename T>void wr(T x)
{
	if(x<0)putchar('-'),x=-x;
	if(x>9)wr(x/10);
	putchar((x-x/10*10)^48);
	return ;
}//快写 
signed main()
{
//	freopen("krumpirkokrumpirko2.in","r",stdin);
	read(n);read(L);
	for(int i=1;i<=n;i++) read(a[i]),suma+=a[i];
	for(int i=1;i<=n;i++) read(c[i]),sumc+=c[i];
	memset(dp_n,127,sizeof dp_n);
	ans=dp_n[0][0][0];
	memset(dp_x,-127,sizeof dp_x);
	dp_x[0][0][0]=dp_n[0][0][0]=0;
	for(int i=1;i<=n;i++)
	{
		for(int j=0;j<=min(i,L);j++)
		{
			for(int k=0;k<=suma;k++)
			{
				dp_n[i&1][j][k]=dp_n[(i-1)&1][j][k]; 
				dp_x[i&1][j][k]=dp_x[(i-1)&1][j][k];
				if(k>=a[i]&&j)
				{
					dp_n[i&1][j][k]=min(dp_n[i&1][j][k],dp_n[(i-1)&1][j-1][k-a[i]]+c[i]);
					dp_x[i&1][j][k]=max(dp_x[i&1][j][k],dp_x[(i-1)&1][j-1][k-a[i]]+c[i]);
				}
			}
		}
	}
	for(int i=0;i<=suma;i++)
	{
		if(dp_n[n&1][L][i]<1e10) ans=min(ans,dp_n[n&1][L][i]*(sumc-dp_n[n&1][L][i])*1.0/(i*(suma-i)));
		if(dp_x[n&1][L][i]>-1e10) ans=min(ans,dp_x[n&1][L][i]*(sumc-dp_x[n&1][L][i])*1.0/(i*(suma-i)));
	}
	printf("%.3lf\n",ans);
	return 0;
 } 

标签:le,int,样例,times,土豆,KRUMPIRKO,dp
From: https://www.cnblogs.com/llwwll/p/16810072.html

相关文章