input
4
2 9 7
1 9 10
2 8 4
1 7 9
output
34
博主是一个菜鸟,期望各位大佬能进行指点。
读完题目之后,我们不妨来回顾一下高中的排列组合之插空法与捆绑法。
捆绑法
使用方式:将相邻元素捆绑在一起,看成一个整体。
插空法
使用方式:先安排除了不相邻以外的其它元素,再将不相邻元素插空。
思路:
步骤一:
对每一种性格进行捆绑和分组:
情况1.在没有pi<qi的情况下,把所有同种性格的同学捆绑在一起,并把min(pi-qi)对应的同学移动到最左边,并加入A组。
情况2.在有pi<qi的情况下,把符合(pi<qi)的同学捆绑在一起,并把在pi<qi下的max(qi)对应的同学移动到捆绑同学的最左边,然后把捆绑的同学和未捆绑的同学组成一个Bi组,然后加入B组。
完成步骤一,可以得到一组在同一性格下的数据:
1.只有一个数据。
2.多个数据,并且每个数据的pi<qi。
步骤二:
进行插空或插空加捆绑:
不妨设:
B.size=B0.size+B1.size+…+Bn-1.size,
maxsize=max(Bi.size),
B_size=(B.size-maxsize),
A.size。
情况1:maxsize-1<=B_size+A.size
结果很显然同种性格的数据必定不相邻。
情况2:maxsize-1>B_size+A.size
不妨设maxsize对应得的Bi为Bm组,因此Bm组内会有Q=maxsize-B_size-A.size个数据要进行捆绑。对Bm组关于min(qi-pi)进行升排序,取前Q个数据进行捆绑,并把第1个放在捆绑的最左边,接下来参考情况1。
#include<iostream>
#include<vector>
#include<algorithm>
#include<unordered_map>
using namespace std;
struct node {
int kind;
int p, n;
node(int kind,int p,int n):kind(kind),p(p),n(n){
}
node(){
}
};
bool cmp(node A, node B) {
return A.n < B.n;
}
bool cmp1(vector<node> A, vector<node> B) {