输入:
2 //n个事件
3 1 //事件持续时间,事件规定的deadline
3 0
1 //m个需要连续的事件
1 2 //让第1、2个事件连续
输出:6
如果事件运行结束时间要比规定的deadline晚,则结束时间-deadline是需要付出的惩罚的金币
如果有更大的惩罚的段,则比这个小的段就不计入
如: 连续1、2事件后,对第一事件,结束时间-规定时间= 3 - 1 = 2 需惩罚3个金币
对第二事件,结束-规定 = 6 - 0 = 6
所以2<6, 只需付6个金币。
做题思路:
把连起来的几个事件,找出最大的金币 (如果中间截断,则重新计入比较)
把没连起来的单个事件,也求其最大金币
从小到大排序(把最小的数放在前面,后面需要加的大的数的次数就少些)
然后连续加起来就是需付出的最小的金币
如:1,2,4,7
则需付1 + (1+2)+(1+2+4)+(1+2+4+7)即可。
//
// main.cpp
// wangyi3
//
// Created by zjl on 16/9/18.
// Copyright © 2016年 zjl. All rights reserved.
//
#include <iostream>
#include <vector>
#include <set>
using namespace std;
int main(int argc, const char * argv[]) {
// insert code here...
int n;
while(cin >> n){
vector<vector<int>>num(n, vector<int>(2,0));
for(int i = 0; i < n; i++)
cin >> num[i][0] >> num[i][1];
int m;
cin >> m;
vector<vector<int>>seq(m, vector<int>(2,0));
for(int i = 0; i < m; i++)
cin >> seq[i][0] >> seq[i][1];
vector<bool>judge(n+1, false);
int mini = min(num[seq[0][0]-1][1], num[seq[0][1]-1][1]);
int maxn = num[seq[0][0]-1][0] + num[seq[0][1]-1][0] - mini;
int max_res = maxn;
judge[seq[0][0]] = true;
judge[seq[0][1]] = true;
vector<int>s;
int i = 1;
for(; i < m; i++){
if(seq[i][0] == seq[i-1][1]){
maxn += num[seq[i][1]-1][0] + mini;
mini = min(mini, num[seq[i][1]-1][1]);
maxn -= mini;
}else{
max_res = max(maxn, max_res); //如果截断了,如1、2, 4、5,则4开头的重新算
s.push_back(max_res);
mini = min(num[seq[i][0]-1][1], num[seq[i][1]-1][1]);
maxn = num[seq[i][0]-1][0] + num[seq[i][1]-1][0] - mini;
}
judge[seq[i][0]] = true;
judge[seq[i][1]] = true;
}
if(m == 1)
s.push_back(max_res);
if(i == m && m > 1){ //最后一组也连接上一组的,则需处理结果
--i;
if(seq[i][0] == seq[i-1][1]){
max_res = max(maxn, max_res);
s.push_back(max_res);
}
}
for(int k = 1; k <= n; k++){
if(judge[k] == false)
s.push_back(num[k-1][0] - num[k-1][1]);
}
sort(s.begin(), s.end());//排序
int part = 0;
int res = 0;
for(int i = 0; i < s.size(); i++){
part +=s[i];
res += part;
}
/*
int res = s[0];
for(int i = 1; i < s.size(); i++){
res = max(res, s[i]);
}
*/
cout<<res<<endl;
}
return 0;
}