10月11日 二分答案(Monthly Expense)

问题:

 给出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是个暴力的东西…

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_viceversa

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值