其他分享
首页 > 其他分享> > G. Minimal Coverage(二分)

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