IOI 2017 Practice Contest mountains
Mountains
题意:
选最多的点使得两两看不见。
分析:
分治,solve(l,r)为区间[l,r]的答案。那么如果不选最高点,分治两边即可,选了最高点,那么在最高点看不见的区间里分治。
代码:
1 #include"mountains.h" 2 #include<bits/stdc++.h> 3 using namespace std; 4 5 const int N = 2010; 6 int y[N]; 7 int f[N][N]; 8 9 bool Judge(int a,int b,int c) { // a see c ? 10 // ((y[a] - y[b]) / (a - b)) > ((y[a] - y[c]) / (a - c)); 11 return 1ll * (y[a] - y[b]) * (a - c) > 1ll * (y[a] - y[c]) * (a - b); 12 } 13 14 int solve(int l,int r) { 15 if (f[l][r]) return f[l][r]; 16 if (l > r) return 0; 17 if (l == r) return 1; 18 int pos = -1, mx = -1; 19 for (int i=l; i<=r; ++i) if (y[i] > mx) pos = i, mx = y[i]; 20 int ans1 = solve(l, pos - 1) + solve(pos + 1, r); // select max_height_node 21 22 int ans2 = 0; // don't select this node 23 for (int i=pos-1,j; i>=l; i=j) { 24 for (j=i-1; j>=l; --j) { // i can see pos 25 if (Judge(j, i, pos)) { // j can't see pos 26 if (j == l) ans2 += solve(l, i - 1); 27 continue; 28 } 29 if (j + 1 <= i - 1) ans2 += solve(j + 1, i - 1); // this Section can't see pos 30 break; 31 } 32 } 33 for (int i=pos+1,j; i<=r; i=j) { 34 for (j=i+1; j<=r; ++j) { 35 if (Judge(pos, i, j)) { 36 if (j == r) ans2 += solve(i + 1, r); 37 continue; 38 } 39 if (i + 1 <= j - 1) ans2 += solve(i + 1, j - 1); 40 break; 41 } 42 } 43 return f[l][r] = max(ans1, ans2 + 1); 44 } 45 46 int maximum_deevs(vector<int> A) { 47 int n = A.size(); 48 for (int i=1; i<=n; ++i) y[i] = A[i - 1]; 49 return solve(1, n); 50 }