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

来源:互联网 发布:淘宝美工要学哪些软件 编辑:程序博客网 时间:2024/06/02 21:34

问题:

 给出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;elsebelow = mid+1;}cout << mid;system("pause");return 0;}
说句题外话,这题让我想到了CUMCM2011B(交巡警平台),第二问要求“封锁城市最佳方案”,很多人理解为总时间,这个是不对的,应该理解成各个平台封锁对应路口最小时间的最大。那题先用dijkstra计算出距离矩阵,再用二分答案求,判断上应该比这个好做一点。

据说当年想到的人都是用lingo暴力求解的,诚然math model是个暴力的东西…

原创粉丝点击