资源限制
时间限制:1.0s 内存限制:256.0MB
问题描述
Hugh Samston经营着一个为今年的ICPC世界总决赛的参与者提供甜点的餐饮服务。他将会提供上面有冰激凌的饼片。为了满足不同的需求,他准备了许多不同的饼片和冰激凌。
Hugh希望以一份饼片上一份冰激凌的方式来提供甜点。然而,作为一个商人,他希望能赚到尽可能多的钱。他知道不同种类的饼片和冰激凌组合的价格,也知道那些冰激凌和那些饼片不能组合在一起。
Hugh想根据每种饼片和冰激凌的数量,以及之前提到的不同组合的情况,确定他能获得的利润的范围。
输入格式
测试数据的输入一定会满足的格式。
输入的第一行包含两个整数P, I,分别表示饼片和冰激凌的种类数。
接下来一行包含P个整数,表示每种类型饼片的数量。
接下来一行包含I个整数,表示每种类型冰激凌的数量。
接下来P行,每行包含I个实数,表示每种类型饼片和冰激凌组合的结果。
如果这种饼片和这种冰激凌可以组合,则为一个(0,10)的实数,表示这种组合的收益。
否则,则为-1,表示这两种之间不能组合。
输出格式
输出一行,以"(最小收益) to (最大收益)"的方式输出利润的范围。
请注意:所有的饼片和冰激凌都必须用完。
样例输入
2 3
40 50
27 30 33
1.11 1.27 0.70
-1 2 0.34
样例输出
91.70 to 105.87
数据规模和约定
0 < P,I <= 50,每种类型饼片或冰激凌数量不超过100。
该算法之我的思路
- 根据题可知应对除-1之外的组合数组的值排序,
1.从大到小得到数据后,处理数据得到最大效益
2.从小到大得到数据后,处理数据得到最小效益 - 算法本身不难,不过需要注意使用的存储变量是否足够计算。我写的算法没有优化空间使用部分,然而大致思路可以参考。
算法展示
#include <iostream>
#include <iomanip>
using namespace std;
double find_min(int Ps[],int Is[],int sign[],double PsIp[],int P,int I,int i,int tempn,double MIN)
{
int min;
double minv;
//记录最小收益
while(tempn>0)
{
min=0,minv=10.0;
for(i=0;i<(P*I);i++)
{
if(sign[i]>0)//sign[i]==0代表已记录, sign[i]==-1代表不能组合
{
if(minv>PsIp[i])
{
minv = PsIp[i];
min = i;
}
}
}
//计算最小收益
if(Ps[min/I]<Is[min%I])
{
MIN+=Ps[min/I]*minv;
Is[min%I]=Is[min%I]-Ps[min/I];
tempn-=Ps[min/I];
Ps[min/I]=0;
}else
{
MIN+=Is[min%I]*minv;
Ps[min/I]=Ps[min/I]-Is[min%I];
tempn-=Is[min%I];
Is[min%I]=0;
}
//处理数据
sign[min]=0;
}
return MIN;
}
double find_max(int Ps[],int Is[],int sign[],double PsIp[],int P,int I,int i,int tempx,double MAX)
{
int max;
double maxv;
//记录最大收益
while(tempx>0)
{
max=0,maxv=0.0;
for(i=0;i<(P*I);i++)
{
if(sign[i]>0)//sign[i]==0代表已记录, sign[i]==-1代表不能组合
{
if(maxv<PsIp[i])
{
maxv = PsIp[i];
max = i;
}
}
}
//计算最大收益
if(Ps[max/I]<Is[max%I])
{
MAX+=Ps[max/I]*maxv;
Is[max%I]=Is[max%I]-Ps[max/I];
tempx-=Ps[max/I];
Ps[max/I]=0;
}else
{
MAX+=Is[max%I]*maxv;
Ps[max/I]=Ps[max/I]-Is[max%I];
tempx-=Is[max%I];
Is[max%I]=0;
}
//处理数据
sign[max]=0;
}
return MAX;
}
int main()
{
int P,I;
int Ps[51],Is[51],Psx[51],Isx[51],sign[2501];
double PsIp[2501],MIN=0.0,MAX=0.0;
cin>>P>>I;
int i;
//输出数据
int tempn=0,tempx;
for(i=0;i<P;i++)
{
cin>>Ps[i];
tempn+=Ps[i];
Psx[i] = Ps[i];
}
for(i=0;i<I;i++)
{
cin>>Is[i];
Isx[i]=Is[i];
}
for(i=0;i<(P*I);i++)
{
cin>>PsIp[i];
if(PsIp[i]==-1)sign[i]=-1;
else sign[i]=1;
}
tempx = tempn;
MIN = find_min(Ps,Is,sign,PsIp,P,I,i,tempn,MIN);
//恢复Psip[i]未被标记的状态
for(i=0;i<(P*I);i++)
{
if(PsIp[i]==-1)sign[i]=-1;
else sign[i]=1;
}
//记录最大收益
MAX=find_max(Psx,Isx,sign,PsIp,P,I,i,tempx,MAX);
cout.setf(ios::fixed);
cout<<fixed<<setprecision(2)<<MIN<<" to "<<MAX;
return 0;
}