G. Minimal Coverage(二分)
作者:互联网
题意:
给定\(n\)条线段,对应长度为\(s_i\),初始所在点为\(0\),按顺序进行放置,即在前一点的基础上进行\(-s_i,+s_i\)操作,求覆盖区间最短长度。
思路:
二分。
因为线段长度不超过\(1000\),所以覆盖区间长度不超过\(2000\),在区间\([0,2000]\)二分答案。若最短区间长度为\(k\),无论怎样操作,覆盖区间总能移到区间\([0,k]\)内,只是初始所在点不一定为\(0\)。
code:
#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <algorithm>
#include <queue>
#include <stack>
#include <vector>
#include <deque>
#include <cmath>
#include <ctime>
#include <map>
#include <set>
#include <unordered_map>
#define fi first
#define se second
#define pb push_back
#define endl "\n"
#define debug(x) cout << #x << ":" << x << endl;
#define bug cout << "********" << endl;
#define all(x) x.begin(), x.end()
#define lowbit(x) x & -x
#define fin(x) freopen(x, "r", stdin)
#define fout(x) freopen(x, "w", stdout)
#define ull unsigned long long
#define ll long long
const double eps = 1e-15;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const double pi = acos(-1.0);
const int mod = 1e9 + 7;
const int maxn = 1e4 + 10;
using namespace std;
int n, s[maxn], t;
int dp[maxn][2010];
bool judge(int k){
for(int i = 0; i <= n; i ++){
for(int j = 0; j <= 2000; j ++)dp[i][j] = (i == 0 ? 1 : 0);
//当i=0时,假设初始点在j
}
for(int i = 1; i <= n; i ++){
for(int j = 0; j <= k; j ++){
if(dp[i - 1][j] && j + s[i] <= k)dp[i][j + s[i]] = 1;
if(dp[i - 1][j] && j - s[i] >= 0)dp[i][j - s[i]] = 1;
}
}
for(int i = 0; i <= k; i ++)if(dp[n][i])return true;
return false;
}
void solve(){
scanf("%d", &n);
for(int i = 1; i <= n; i ++)scanf("%d", &s[i]);
int l = 0, r = 2000;
while(l < r){
int mid = l + r >> 1;
if(judge(mid))r = mid;
else l = mid + 1;
}
printf("%d\n", l);
}
int main(){
scanf("%d", &t);
while(t --)solve();
return 0;
}
此题还可以用dp做(dp太菜了wwwwwww)
标签:二分,mid,dp,Coverage,区间,长度,include,Minimal,define 来源: https://www.cnblogs.com/lniiwuw/p/15359698.html