/*
* poj 1064 Wooden Sticks
题目大意:
给定一系列木棍,每个木棍有两个属性长度l和重量w,这些木棍要放到某台机器中进行处理。
机器处理每个木棍前有一段时间的做准备工作,其规则如下:
1)处理第一条木棍前准备时间为1
2)如果后面处理的木棍的属性满足l'>l并且w'>w则无需准备,否则需要时间为1的准备
现在需要你编写程序,给出指定输入的木棍需要的最少准备时间值。
解题思路:
1、将所有木棍按照其中一个属性从小到大排序,这里选择属性l
2、求解排序后的序列中w属性的最长严格下降子序列的长度
数学模型:
LDS -- 最长严格下降子序列长度
f(i)表示以i个元素为尾的最长严格下降子序列的长度,则有如下递归式成立:
f(i) = max{f(k) | k<i 并且 a[k]>a[i]} + 1
正确性证明:
假设排序后的木棍如下:
i| 1 2 3 | 4 5 6 7 | 8 9
-|------------|---------------|-------
l| 1 2 3 | 4 5 6 7 | 8 9
| | |
w| a b f | c d e i | g h
本例所需准备时间是2 -- 最长严格下降子序列的长度,具体排列如下:
i| 1 2 3 4 5 6 | 7 8 9
-|------------------------|-----------
l| 1 2 4 5 6 7 | 3 8 9
| |
w| a b c d e i | f g h
*/
#include <iostream>
#include <cstdio>
#include <cstdlib>
namespace {
using namespace std;
typedef struct STICK
{
int l, w;
}STICK_S;
int stick_cmp(const void *pOP1, const void *pOP2)
{
STICK_S *ps1 = (STICK_S *)pOP1;
STICK_S *ps2 = (STICK_S *)pOP2;
if (ps1->l < ps2->l) return -1;
/*
注意,如果属性1相同的话,还需要按照属性2的大小排序
这是因为,最长下降子序列长度取决于元素的排列
*/
if (ps1->l == ps2->l)
{
if (ps1->w < ps2->w) return -1;
if (ps1->w == ps2->w) return 0;
if (ps1->w > ps2->w) return 1;
}
if (ps1->l > ps2->l) return 1;
}
const int N_MAX = 5000;
STICK_S sticks[N_MAX];
int f[N_MAX];
int n;
int wooden_sticks()
{
qsort(sticks, n, sizeof(sticks[0]), stick_cmp);
int t=1;
for (int i=0; i<n; i++)
{
f[i] = 1; // 初始化
for (int j=0; j<i; j++)
{
if (sticks[j].w>sticks[i].w && (f[j]+1)>f[i])
f[i] = f[j]+1; // 更新f[i]
}
if (f[i]>t) t=f[i]; // 更新最大长度
}
return t;
}
}
int main()
{
int T;
scanf("%d", &T);
for (int t=0; t<T; t++ )
{
scanf("%d", &n);
for (int i=0; i<n; i++)
{
scanf("%d%d", &sticks[i].l, &sticks[i].w);
}
printf("%d\n", wooden_sticks());
}
return 0;
}
poj 1065 Wooden Sticks
最新推荐文章于 2021-02-07 23:59:09 发布