題目: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
新聞熱點
疑難解答