题目大意:
给n根木棍的长度和重量。根据要求求出制作木棍的最短时间。建立第一个木棍需要1分钟,若是接着要制作的木棍重量和长度都比此木棍长就不需要建立的时间,若是没有,则再需要建立时间。求时间最小为多少。
传说中的动态规划第一题。。。光看英语题就看了好久。。。
本题刚开始一看,这尼玛真简单,排个序筛选就行了,然而还是我图样。。。
拿第一个样例来说,排好序(1, 4),(2,1),(3,5),(4,9),(5,2)。而最后最好的方案是(5,2)、(2,1);(4,9)、(3,5)、(1, 4)两种。换句话说,排好序后并不是按照顺序筛选,而是无规律的可以跳着筛选,从而找出方案。
这就要求运用动态规划思想,所处理的数组是动态的而不是静态的,时刻在更新,这可能就是DP的核心。
本题关键是这一段代码:
for(i = 1; i <= n; i ++)
{
k = lower_bound(g + 1, g + n + 1, sti[i].wei) - g;//1
ans = max(ans, k);//2
g[k] = sti[i].wei;//3
}
首先按照长度优先降序排序。
1、运用二分查找返回该元素在数组中的下标值,lower_bound是返回大于等于该元素指针(upper_bound是返回大于该元素指针,不能靠字面意思猜测= =);2、ans的值为动态数组g中有效元素的个数(初始为INF);
3、通过刷新缩小有效元素的值。
下面演示:
1、处理(5,2),k = 1,ans = 1,g[0] = 2;
2、处理(4,9),k = 2,ans = 2,g[0] = 2,g[1] = 9;
3、处理(3,5),k = 2,ans = 2,g[0] = 2,g[1] = 5;
4、处理(2,1),k = 1,ans = 2,g[0] = 1,g[1] = 5;
5、处理(1,4),k = 2,ans = 2,g[0] = 1,g[1] = 4。
也就是说,有效数组只存储一些阈值(有效值),而其余无效值来更新这些值从而缩小范围。所谓的有效,就是以一级排序优先,二级排序基本有序,这才能算有效。
此外排序函数自己写也是计算机的一个优势,真的好神奇哦~
AC代码:
#include <stdio.h>
#include <string.h>
#include <cstdio>
#include <algorithm>
using namespace std;
const int N = 5005;
const int INF = 1<<27;
struct STI
{
int len;
int wei;
}sti[N];
bool cmp(STI a, STI b)
{
if(a.len != b.len)
return a.len > b.len;
else
return a.wei > b.wei;
}
int main()
{
// freopen("in.txt", "r", stdin);
int T, n, i, k, weight, ans;
int g[N];
scanf("%d", &T);
while(T --)
{
scanf("%d", &n);
for(int i = 1; i <= n; i ++)
{
scanf("%d%d", &sti[i].len, &sti[i].wei);
g[i] = INF;
}
// memset(g, INF, sizeof(g));
sort(sti + 1, sti + n + 1, cmp);
ans = 0;
for(i = 1; i <= n; i ++)
{
k = lower_bound(g + 1, g + n + 1, sti[i].wei) - g;
ans = max(ans, k);
g[k] = sti[i].wei;
}
printf("%d\n", ans);
}
return 0;
}