5.7线性动态规划1
P2285 [HNOI2004] 打鼹鼠
#include<bits/stdc++.h>
using namespace std;
struct node{int x, y, t;
}a[100010];
int dp[100010];
void solve(){int n, m; cin >> n >> m;for(int i = 1; i <= m; i++){cin >> a[i].t >> a[i].x >> a[i].y;}int maxx = 0;for(int i = 1; i <= m; i++){dp[i] = 1;for(int j = 1; j < i; j++){if((abs(a[i].x - a[j].x) + abs(a[i].y - a[j].y)) <= (a[i].t - a[j].t)){dp[i] = max(dp[i], dp[j] + 1);}}maxx = max(maxx, dp[i]);}cout << maxx << endl;
}
signed main(){ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);solve();return 0;
}
P1020 [NOIP 1999 提高组] 导弹拦截
#include<bits/stdc++.h>
using namespace std;
const int N = 50010;
int a[N], b[N];
void solve(){int cnta = 0, cntb = 0, x;while(cin >> x){//最长不上升子序列的长度==最少上升子序列的个数 int s = 0;int l = -1, r = cnta;while(l + 1 != r){int mid = l + r >> 1;if(a[mid] < x)r = mid;else l = mid;}if(r != cnta){a[r] = x;s = 1;}/*for(int i = 0; i < cnta; i++){if(a[i] < x){a[i] = x;s = 1;break;}}*/if(!s)a[cnta++] = x;//最少不上升子序列的个数==最长上升子序列的长度 s = 0, l = -1, r = cntb;while(l + 1 != r){int mid = l + r >> 1;if(b[mid] >= x)r = mid;else l = mid;}if(r != cntb){b[r] = x;s = 1;}/*for(int i = 0; i < cntb; i++){if(b[i] >= x){b[i] = x;s = 1;break;}}*/if(!s)b[cntb++] = x;}cout << cnta << endl << cntb << endl;
}
signed main(){ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);solve();return 0;
}
P1725 琪露诺
#include<bits/stdc++.h>
using namespace std;
const int N = 400010;
int dp[N];
void solve(){int n, l, r; cin >> n >> l >> r;for(int i = 0; i <= n; i++)cin >> dp[i];for(int i = n - l; i >= 0; i--){int s = -1e9;for(int j = l; j <= r; j++){s = max(s, dp[i + j]);}dp[i] += s;}cout << dp[0] << endl;
}
signed main()
{ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);solve();return 0;
}
做法2:单调队列
#include<bits/stdc++.h>
using namespace std;
const int N = 400010;
int dp[N];
void solve(){deque<int> q; int n, l, r; cin >> n >> l >> r;for(int i = 0; i <= n; i++)cin >> dp[i];q.push_back(n + 1);//把n + 1索引的0加进去,防止负数影响 for(int i = n - l; i >= 0; i--){if(q.front() > i + r)q.pop_front();//不在滑动窗口if(!q.empty()){while(dp[i + l] > dp[q.back()]){//把小的丢掉 q.pop_back();if(q.empty())break;}} q.push_back(i + l);//放入大的索引 dp[i] += dp[q.front()];//窗口最大值 }cout << dp[0] << endl;
}
signed main()
{ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);solve();return 0;
}