题目:http://acm.hdu.edu.cn/showproblem.php?pid=1257
可以这样理解题意:给出一组数字,给它们划分组数,划分的依据是,每一组的元素必须是单调递减的顺序,只有这样才能保证一个拦截系统能拦截本组的所有导弹,待求的是这样划分的最小组数.
方法一:直接模拟人工分组的过程
例如389 207 155 300 299 170 158 65的划分过程如下
首先,遍历一遍,389->207->155->65为第一组,再看剩余的.
其次,300->299->170->158为第二组.
最少需要2个拦截系统.
C++代码如下
#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
int n;
while(cin >> n)
{
int *a = new int[n];
for(int i=0;i<n;i++)
cin >> a[i];//输入数据
int result = 0;
for(int i=0;i<n;i++)//从头到尾,分别以每个元素作为起点,遍历一遍(也可以不这样,只要所有元素能得到分配即可)
{
if(a[i])//元素是否分配,开始数据均非0,是未分配的,到后面会陆续将它们设为0
{
int * IndexOfShouldBeZero = new int[n];//可以分配的元素的下标
int NumOfShouldBeZero = 0;//可以分配的元素的个数
IndexOfShouldBeZero[NumOfShouldBeZero++] = i;//如果可以进入这个if语句,表明原来是没有被分配的,所以现在可以分配了
result ++;//组数加1(元素i是本组的第一个元素)
for(int j=i+1;j<n;j++)//看看元素i之后的所有的、没有分配的 元素
{
if(a[j])//没有分配的
{
if(a[j]<a[IndexOfShouldBeZero[NumOfShouldBeZero-1]])//元素j可以分配,因为它比前一个元素小
{ //思考:前一个元素为什么不是a[j-1].这里要求是这一轮的前一个元素
IndexOfShouldBeZero[NumOfShouldBeZero++] = j;//记录下可以分配到改组的元素下标,以便后面将同一组中的元素统一退出系统
}
}
}
for(int k=0;k<NumOfShouldBeZero;k++)
{
a[IndexOfShouldBeZero[k]] = 0;//让处于同一个组中的元素退出系统,以后不(用)再 考虑它们
}
}
}
cout << result << endl;
}
return 0;
}
上述代码提交AC.
方法二:换一种思路
参考:http://blog.csdn.net/dxx_111/article/details/48864239
将第一个导弹的高度设置为第一个拦截系统的值,之后遍历所有的导弹高度,遇到一个导弹,在已有的拦截系统中查找,看看已有的拦截系统能否拦截这个导弹.
如果能拦截,则拦截.并且将查找到的可以拦截这个导弹的拦截系统的值设置为该导弹的高度,为的是保证【递减】的要求.
如果不能,则只能添加新的拦截系统.并且新的拦截系统的值设置为该导弹的高度.
C++代码如下
#include<iostream> #include<algorithm> using namespace std; int main() { int n; while(cin>>n) { int *a = new int[n]; int *H = new int[n];//最多需要n个拦截系统 int num = 0; for(int i=0;i<n;i++) { cin >> a[i]; } H[num++] = a[0]; for(int i=1;i<n;i++) { int ok = 0; for(int j=0;j<num;j++) { if(a[i]<H[j]) //如果在已经有的拦截系统中,可以拦截导弹i,那么不用添加新的拦截系统 { ok = 1; H[j] = a[i];//并且将第一次找到的拦截系统的值设置为该导弹的高度,为的是,符合【递减】的要求 break; } } if(ok==0)//否则,需要添加新的拦截系统,并且把新的拦截系统的值设置为该导弹的高度 { H[num++] = a[i]; } } cout << num << endl; } return 0; }上述代码提交AC.
方法三:动态规划
参考:http://www.cnblogs.com/dongsheng/archive/2012/07/23/2604777.html