http://www.lightoj.com/volume_showproblem.php?problem=1017
题意:给出刷子的宽和最多横扫次数,问被扫除最多的点是多少个。
思路:状态设计DP[i][j]代表刷子下边界为i已用了j次时最大个数。决策为扫和跳过。
/** @Date : 2016-12-18 14:25:51 * @FileName: LightOJ 1017 DP?.cpp * @Platform: Windows * @Author : Lweleth (SoundEarlf@gmail.com) * @Link : https://github.com/Lweleth * @Version : $Id$ */ // #include <stdio.h> // #include <iostream> // #include <string.h> // #include <algorithm> // #include <utility> // #include <vector> // #include <map> // #include <set> // #include <string> // #include <stack> // #include <queue> #include<bits/stdc++.h> #define LL long long #define PII pair<int ,int> #define MP(x, y) make_pair((x),(y)) #define fi first #define se second #define PB(x) push_back((x)) #define MMG(x) memset((x), -1,sizeof(x)) #define MMF(x) memset((x),0,sizeof(x)) #define MMI(x) memset((x), INF, sizeof(x)) using namespace std; const int INF = 0x3f3f3f3f; const int N = 1e5+20; const double eps = 1e-8; int y[110]; int dp[110][110]; int n, w, k; int ref(int s, int k) { if(s >= n || k < 1) return 0; if(dp[s][k] != -1) return dp[s][k]; int sp, sk; int cnt = 0; int i;//考虑有负数的情况 for(i = s; i < n; i++) { if(y[i] - y[s] <= w) cnt = i - s + 1; else break; } sp = cnt + ref(i, k - 1);//选择扫 sk = ref(s + 1, k);//跳过 dp[s][k] = max(sp, sk); return dp[s][k]; } int main() { int T; int cnt = 0; cin >> T; while(T--) { scanf("%d%d%d", &n, &w, &k); for(int i = 0; i < n; i++) { int x; scanf("%d%d", &x, y + i); } sort(y, y + n); MMG(dp); int ans = ref(0, k); printf("Case %d: %d ", ++cnt, ans); } return 0; }