洛谷P1020 导弹拦截

链接

  https://www.luogu.org/problem/show?pid=1020

题解

  第一问,直接DP。

  关于第二问:就是用最少的链串起所有的点。

  考虑新加入一个元素,假设前面的已经用最少的链串起来了。那么当前点该加到哪一条链上?

  如果我们记录了前面每一个点的next(即所在链的下一个点)。如果next为空,且这个点的权值≥新加入点的权值,就可以直接把新加入的点串到后面,这肯定是最优的选择。

  但如果扫描了前面所有的点,都没找到上述情况的话,我可以新开辟一条链,并以当前点为首点;还有一种选择,把前面一条链断开,把当前点接上去,这样的话链数同样增加了1。不难发现,这两种决策是等价的。因为后面再来点的时候,接到这两条链的末端造成的情形是一样的,在这两条链的某处断开,造成的情形也是一样的。所以说这两种操作没有什么区别...,因此我们就可以不考虑断链的决策,只是在后面添加或者开辟新链,这样这道题就很好写了。记录链数和每条链末端的权值,每次来一个点就扫描所有的末端,如果找到合适的末端就把那个末端的权值改成当前点的权值,否则新建一个末端,权值等于当前点权值。

  时间复杂度O(N^2)(其实可以优化但没必要)

代码

//dp
#include 
#include 
#define maxn 1000
using namespace std;
int h[maxn], f[maxn], N, ans, list[maxn];
int main()
{
	int i, j;
	for(N=1;~scanf("%d",h+N);N++)
	{
		f[N]=1;
		for(i=1;ilist[0])list[++list[0]]=h[i];
	}
	printf("%d",list[0]);
	return 0;
}



你可能感兴趣的:(贪心,#,一般动态规划)