描述
最近要构建一个通信系统。这个系统包含若干个设备,对于每个设备,都可以从不同的商家购买。从不同商家购买的同种设备,在最大带宽和价格上都有所区别。
整个系统的带宽B是指它包含的所有设备的最大带宽的最小值。整个系统的代价P是指它包含的所有设备的价格之和。目标是确定一个购买方案,使得整个系统的性价比B/P最高。
输入
输入包含多行。第1行为n(1<=n<=100)表示系统包含的设备数,接下来的n行格式是这样的,第i+1(1<=i<=n)行的第1个数为mi(1<=mi<=100),表示提供第i种设备的商家数,接下来在这一行内便是mi对个正整数,分别表示对应商家提供此种商品的最大带宽和价格。
输出
输出为一行,是一个3位浮点小数B/P即最优购买方案下系统的最优性价比。
输入样例
3
3 100 25 150 35 80 25
2 120 80 155 40
2 100 100 120 110
输出样例
0.649
一、问题理解:
要构建一个通信系统,该系统包含多个设备,而每个设备有分为不同规格,要设计整个通信系统的最大性价比,则可将问题分解,改求每种设备中性价比最大的,将每种设备里面性价比最大的一个挑出来合并后就是整体性价比最大的方案。
二、设计算法:
算法策略:
先将输入数据抽象成设备对象,以每个设备对象为研究对象计算每个设备的性价比,横向对比每种设备中性价比最大的设备,求出虽有性价比最大的设备,就是性价比最大的方案。
数据结构的选定:结构体数组,用来存储每种设备的信息数据。
求解步骤:
1、 先将输入数据存入array的结构体数组中,有多少种设备即有多少行,每中设备分几种即每行有多少个。
2、 遍历结构体数组,以行为单位,得到每一行中性价比最大的设备,将其存入arraytemp结构体数组中。
3、 步骤2结束后,数组arraytemp中存储的就是每种设备中性价比最大的一个设备,最后将arraytemp中所有设备遍历一遍,得到总金额和最小带宽,求出方案最大性价比。
4、后续对算法的优化
流程图:
三、描述算法:
伪代码:
GetMacBP
FOR I = 0 TO Faci_Number //Faci_Number为设备种数
FOR j = 0 TO Sup_Number[i] – 1 //Sup_Number中存储每种设备有几个规格
IF array[i][j].brandwidth / array[i][j].price
<=
array[i][j + 1].brandwidth / array[i][j + 1].price //取每行中性价比最大的设备
arraytemp[i].brandwidth = array[i][j + 1].brandwidth
arraytemp[i].price = array[i][j + 1].price
FOR I = 0 TO Faci_Number
Countp += arraytemp[i].price
IF minb >= arraytemp[i].brandwidth
Minb = arraytemp[i].brandwidth
Cout << minb << “ “ << countp << endl
Cout << minb / countp << endl
/**************
*结构体定义:
* struct Node
*{
* float brandwidth;
* float price;
*}
*array数组为结构体数组,内部存储所有设备的参数
*arraytemp数组用来存放每种设备中性价比最大的设备参数
**************/
四、证明算法正确性:
初始化:将设备数据存入数组array中,设备种类即数组行数,每种设备的规格树即数组每行包含的个数。
遍历数组:逐个遍历数组,按行为单位,若array[i][j + 1]的性价比比上一个大,就把这一个设备数据存入arraytemp[i]中,最后每行遍历完后,arraytemp[i]中存储的必然是每一行中性价比最大的设备。
最后求值: 在2遍历完数组后,数组arraytemp中存储的就是每一行中性价比最大的设备,遍历一遍arraytemp数组就可得出最小带宽和总金额,即可得出方案的最大性价比。故算法正确。
五、实现代码:
1、设计结构体:
struct Node
{
float brandwidth;
float price;
Node()
{
brandwidth = 0;
price = 0;
}
};
2、从键盘获取设备数据:
void GetItemsFK()
{
cout << "Input the number of facilities" << endl;
cin >> Faci_Number;
array = new Node *[Faci_Number];
Sup_Number = new int[Faci_Number];
for (int i = 0; i < Faci_Number; i++)
{
cout << "the number of " << i << " facility's supplier" << endl;
cin >> Sup_Number[i];
array[i] = new Node[Sup_Number[i]];
for (int j = 0; j < Sup_Number[i]; j++)
{
cin >> array[i][j].brandwidth >> array[i][j].price;
}
}
}
3、从文件读取数据:
bool GetItemsFF()
{
fstream inFile;
inFile.open("data.txt");
string temp;
string num;
vector<vector<int>> items;
vector<int> item;
int length;
int col = 0;
while (getline(inFile, temp))
{
istringstream is(temp);
while (is >> num)
{
item.push_back(atoi(num.c_str()));
}
items.push_back(item);
item.clear();
}
inFile.close();
Faci_Number = items.size();
array = new Node *[Faci_Number];
Sup_Number = new int[Faci_Number];
for (int i = 0; i < Faci_Number; i++)
{
length = items[i].size();
if (length % 2 != 0)
{
for (int j = 0; j < i; j++)
{
delete[] array[j];
}
delete[] array;
delete[] Sup_Number;
return false;
}
Sup_Number[i] = length / 2;
col = 0;
array[i] = new Node[Sup_Number[i]];
for (int j = 0; j < length; j += 2)
{
array[i][col].brandwidth = items[i][j];
array[i][col].price = items[i][j + 1];
col++;
}
}
return true;
}
4、计算最大性价比:
void GetMaxBP()
{
arraytemp = new Node[Faci_Number];
for (int i = 0; i < Faci_Number; i++)
for (int j = 0; j < Sup_Number[i] - 1; j++)
{
if (array[i][j].brandwidth / array[i][j].price <= array[i][j + 1].brandwidth / array[i][j + 1].price)
{
arraytemp[i].brandwidth = array[i][j + 1].brandwidth;
arraytemp[i].price = array[i][j + 1].price;
}
}
float countp = 0;
float minb = arraytemp[1].brandwidth;
for (int i = 0; i < Faci_Number; i++)
{
countp += arraytemp[i].price;
if (minb >= arraytemp[i].brandwidth)
{
minb = arraytemp[i].brandwidth;
}
}
cout << minb << endl;
cout << countp << endl;
printf("%.3f\n", minb / countp);
for (int i = 0; i < Faci_Number; i++)
{
delete[] array[i];
}
delete[] array;
delete[] arraytemp;
delete[] Sup_Number;
}
六、所有代码:
#include <iostream>
#include <vector>
#include <fstream>
#include <sstream>
#include <stdio.h>
using namespace std;
struct Node
{
float brandwidth;
float price;
Node()
{
brandwidth = 0;
price = 0;
}
};
class MaxBP
{
private:
int Faci_Number;
int *Sup_Number;
Node *arraytemp;
Node **array;
public:
void GetMaxBP()
{
arraytemp = new Node[Faci_Number];
for (int i = 0; i < Faci_Number; i++)
for (int j = 0; j < Sup_Number[i] - 1; j++)
{
if (array[i][j].brandwidth / array[i][j].price <= array[i][j + 1].brandwidth / array[i][j + 1].price)
{
arraytemp[i].brandwidth = array[i][j + 1].brandwidth;
arraytemp[i].price = array[i][j + 1].price;
}
}
float countp = 0;
float minb = arraytemp[1].brandwidth;
for (int i = 0; i < Faci_Number; i++)
{
countp += arraytemp[i].price;
if (minb >= arraytemp[i].brandwidth)
{
minb = arraytemp[i].brandwidth;
}
}
cout << minb << endl;
cout << countp << endl;
printf("%.3f\n", minb / countp);
for (int i = 0; i < Faci_Number; i++)
{
delete[] array[i];
}
delete[] array;
delete[] arraytemp;
delete[] Sup_Number;
}
void GetItemsFK()
{
cout << "Input the number of facilities" << endl;
cin >> Faci_Number;
array = new Node *[Faci_Number];
Sup_Number = new int[Faci_Number];
for (int i = 0; i < Faci_Number; i++)
{
cout << "the number of " << i << " facility's supplier" << endl;
cin >> Sup_Number[i];
array[i] = new Node[Sup_Number[i]];
for (int j = 0; j < Sup_Number[i]; j++)
{
cin >> array[i][j].brandwidth >> array[i][j].price;
}
}
}
bool GetItemsFF()
{
fstream inFile;
inFile.open("data.txt");
string temp;
string num;
vector<vector<int>> items;
vector<int> item;
int length;
int col = 0;
while (getline(inFile, temp))
{
istringstream is(temp);
while (is >> num)
{
item.push_back(atoi(num.c_str()));
}
items.push_back(item);
item.clear();
}
inFile.close();
Faci_Number = items.size();
array = new Node *[Faci_Number];
Sup_Number = new int[Faci_Number];
for (int i = 0; i < Faci_Number; i++)
{
length = items[i].size();
if (length % 2 != 0)
{
for (int j = 0; j < i; j++)
{
delete[] array[j];
}
delete[] array;
delete[] Sup_Number;
return false;
}
Sup_Number[i] = length / 2;
col = 0;
array[i] = new Node[Sup_Number[i]];
for (int j = 0; j < length; j += 2)
{
array[i][col].brandwidth = items[i][j];
array[i][col].price = items[i][j + 1];
col++;
}
}
return true;
}
};
int main()
{
MaxBP maxBP;
//maxBP.GetMaxBP();
char flag;
while (true)
{
cout << "键盘输入<K/k>还是文件读入<F/f>(输入N/n退出): ";
cin >> flag;
if (flag == 'K' || flag == 'k')
{
maxBP.GetItemsFK();
maxBP.GetMaxBP();
}
else if (flag == 'F' || flag == 'f')
{
if (maxBP.GetItemsFF()) //
maxBP.GetMaxBP();
else
{
cout << "文件输入不规范,每个设备都有两个参数" << endl;
}
}
else if (flag == 'N' || flag == 'n')
{
break;
}
else
{
cout << "没这回事!" << endl;
}
}
return 0;
}