【题目链接】
http://poj.org/problem?id=3700
【算法】
对于每一枚导弹,有4种决策 :
1.新建一套递增的系统拦截它
2.新建一套递减的系统拦截它
3.在已经建好的递增拦截系统中任选一个符合条件的拦截
4.在已经建好的递减拦截系统中任选一个符合条件的拦截
如果直接搜索,复杂度显然太高,考虑剪枝 :
1.贪心地思考这个问题,我们发现如果能用已经建好的系统拦截,那么就不需要新建了,如果有递增的符合条件的系统,在这些系统中选最近拦截高度最高的,如果有递减的符合条件的系统,在这些系统中选最近拦截高度最低的
2.显然答案是很小的,每枚导弹至少可以和另一枚导弹“配对”,用一套系统拦截,因此最劣情况下也只需25套拦截系统,不妨使用迭代加深算法
【代码】
#include <algorithm> #include <bitset> #include <cctype> #include <cerrno> #include <clocale> #include <cmath> #include <complex> #include <cstdio> #include <cstdlib> #include <cstring> #include <ctime> #include <deque> #include <exception> #include <fstream> #include <functional> #include <limits> #include <list> #include <map> #include <iomanip> #include <ios> #include <iosfwd> #include <iostream> #include <istream> #include <ostream> #include <queue> #include <set> #include <sstream> #include <stdexcept> #include <streambuf> #include <string> #include <utility> #include <vector> #include <cwchar> #include <cwctype> #include <stack> #include <limits.h> using namespace std; int i,n,tota,totb,step; int a[50],b[50],h[50]; inline bool dfs(int dep) { int i,mx,mn,pos,tmp; if (tota + totb > step) return false; if (dep > n) return true; pos = 0; mx = 0; for (i = 1; i <= tota; i++) { if (a[i] < h[dep] && a[i] > mx) { mx = a[i]; pos = i; } } if (pos) { tmp = a[pos]; a[pos] = h[dep]; if (dfs(dep+1)) return true; a[pos] = tmp; } else { tota++; a[tota] = h[dep]; if (dfs(dep+1)) return true; tota--; } pos = 0; mn = 2e9; for (i = 1; i <= totb; i++) { if (b[i] > h[dep] && b[i] < mn) { mn = b[i]; pos = i; } } if (pos) { tmp = b[pos]; b[pos] = h[dep]; if (dfs(dep+1)) return true; b[pos] = tmp; } else { totb++; b[totb] = h[dep]; if (dfs(dep+1)) return true; totb--; } return false; } int main() { while (scanf("%d",&n) && n) { for (i = 1; i <= n; i++) scanf("%d",&h[i]); for (i = 1; i <= n; i++) { memset(a,0,sizeof(a)); memset(b,0,sizeof(b)); tota = totb = 0; step = i; if (dfs(1)) { printf("%d\n",i); break; } } } return 0; }