p.s.自用
题目描述
某工厂生产一批棍状零件,每个零件都有一定的长度(Li)和重量(Wi)。现在为了加工需要,要将它们分成若干组,使每一组的零件都能排成一个长度和重量都不下降(若i<j,则Li<=Lj,Wi<=Wj)的序列。请问至少要分成几组?
输入
第一行为一个整数N(N<=1000),表示零件的个数。第二行有N对正整数,每对正整数表示这些零件的长度和重量,长度和重量均不超过10000。
输出
仅一行,即最少分成的组数。
样例输入 Copy
5 8 4 3 8 2 3 9 7 3 5
样例输出 Copy
2
思路
根据li和wi进行从小到大的排序(li为第一权重,wi为第二权重)。因li一定保持从小打到排序,故可仅根据wi进行分组。
所以,题目则转化为使用贪心算法求解最长不降低子序列个数,可以参考题目:导弹拦截。
参考答案
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <string>
#include <iomanip>
using namespace std;
int main()
{
// 输入
int n; // 个数
cin >> n;
vector<int> li(n); // 长度
vector<int> wi(n); // 重量
for (int i = 0; i < n; i++)
{
cin >> li[i];
cin >> wi[i];
}
// 求解
// 冒泡排序
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n - i - 1; j++)
{
if (li[j] > li[j + 1] || (li[j] == li[j + 1] && wi[j] > wi[j + 1]))
{
int templ = li[j];
li[j] = li[j + 1];
li[j + 1] = templ;
int tempw = wi[j];
wi[j] = wi[j + 1];
wi[j + 1] = tempw;
}
}
}
// 计算:wi-最长不降低子序列 Eg.导弹拦截
vector<int> min_num(1, 0);
min_num[0] = wi[0];
for (int i = 1; i < n; i++)
{
int flag = 0;
for (int j = 0; j < min_num.size(); j++)
{
if (wi[i] >= min_num[j])
{
min_num[j] = wi[i];
flag = 1;
break;
}
}
if (!flag)
min_num.push_back(wi[i]);
}
// 输出
cout << min_num.size() << endl;
}