问题:
给出n天中每天的花费,需要将这些天分成m组,每组包含连续的一天或者多天,若定义第i组花费为$K_i$,求一种分组方法使得$K=max{K_i}$最小
输入样例:
7 5
100
400
300
100
500
101
400
输出样例:
500
这一题是天大书上的题,亲测书上代码有误。
本来acm不应该用vector做,这次练练迭代器操作(虽然也没有练好),我的代码如下:
这里比较坑的可能是判断是否可行,我的做法是先装大的,大的再尽量装大的。
#include<iostream>
#include<vector>
#include<numeric>
using namespace std;
void sort(vector<int> &p)
{
int tmp;
int siz = p.size();
for (int i = 0; i < siz; i++)
{
for (int j = 0; j < siz - 1; j++)
{
if (p[siz - 1 - j] < p[siz - 2 - j])
{
tmp = p[siz - 2 - j];
p[siz - 2 - j] = p[siz - 1 - j];
p[siz - 1 - j] = tmp;
}
}
}
}
int findmax(vector<int>day)
{
vector<int>::iterator a;
int max = 0;
for (a = day.begin(); a != day.end(); a++)
{
if (*a > max)
max = *a;
}
return max;
}
int could(vector<int> day, int top)//输出最少组数,最好改成bool函数。
{
int cur = 0;
int group = 0;
int siz = day.size();
int i = siz;
if (findmax(day) > top)return 10000;
while (--i >= 0)
{
if (day[i] < 0)continue;
cur = day[i];
group++;
if (i == 0)break;
for (int j = i - 1; j >= 0; j--)
{
if (day[j] == -1)continue;
if (cur + day[j] <= top)
{
cur += day[j];
day[j] = -1;
}
}
}
return group;
}
int main()
{
int daynum, groupnum, temp;
vector<int> day;
cin >> daynum;
cin >> groupnum;
for (int i = 0; i < daynum; i++)
{
cin >> temp;
day.push_back(temp);
}
sort(day);
int sum = accumulate(day.begin(), day.end(), 0);
int above = sum, below = 0, mid = (above + below) / 2;
while (below <= above)
{
mid = (above + below) / 2;
if (could(day,mid)<=groupnum)
above = mid-1;
else
below = mid+1;
}
cout << mid;
system("pause");
return 0;
}
说句题外话,这题让我想到了CUMCM2011B(交巡警平台),第二问要求“封锁城市最佳方案”,很多人理解为总时间,这个是不对的,应该理解成各个平台封锁对应路口最小时间的最大。那题先用dijkstra计算出距离矩阵,再用二分答案求,判断上应该比这个好做一点。
据说当年想到的人都是用lingo暴力求解的,诚然math model是个暴力的东西…