[恢]hdu 1051
2011-12-19 02:42:34
地址:http://acm.hdu.edu.cn/showproblem.php?pid=1051
题意:有n个木棍长为l重为w。机器处理木棍,若前一根的l和w均不小于后一根,则不需要额外时间,否则需要额外时间1。问最小需要多少时间。
mark:网上说是贪心,想了很久想不明白,画了一下sample1的图(l当做x,w当做y描点),恍然大悟。
把所有元素按l从大到小排序后,其实就是导弹拦截系统的问题,求一个LIS(关于最少导弹拦截数等于最长非降子序列长度的证明,因为之前和其他同学讨论过,所以知道挺麻烦的。讨论了两天才勉强证出来,还很不简洁,不过这个结论还是对的)。这里数据是5000,所以要用O(nlgn)的方法。O(n^2)理论会超时,不过实际上跑62ms,还好。
代码:
# include <stdio.h>
# include <stdlib.h>
typedef struct node{
int l, w ;
}node ;
node a[5010] ;
int dp[5010] ;
int cmp(const void *a, const void *b)
{
node *p = (node*)a, *q = (node*)b ;
if (p->l != q->l) return q->l - p->l ;
return q->w - p->w ;
}
int main ()
{
int T, n, i, j, ans ;
scanf ("%d", &T) ;
while (T--)
{
scanf ("%d", &n) ;
for (i = 0 ; i < n ; i++)
scanf ("%d%d", &a[i].l, &a[i].w) ;
qsort(a, n, sizeof(node), cmp) ;
ans = -1, dp[0] = 1 ;
for (i = 1 ; i < n ; i++)
{
dp[i] = 1 ;
for (j = 0 ; j < i ; j++)
{
if (a[j].w < a[i].w && dp[j]+1 > dp[i])
dp[i] = dp[j] + 1 ;
}
if (dp[i] > ans) ans = dp[i] ;
}
printf ("%d\n", ans) ;
}
return 0 ;
}