欢迎光临
我们一直在努力

清楚姐姐的布告规划【牛客tracker & 每日一题】

清楚姐姐的布告规划

时间限制:1秒 空间限制:512M

网页链接

牛客tracker

牛客tracker & 每日一题,完成每日打卡,即可获得牛币。获得相应数量的牛币,能在【牛币兑换中心】,换取相应奖品!助力每日有题做,丰盈牛币日益多! 在这里插入图片描述

题目描述

待榜之期,漫长如年。为自己和竹鼠们的生计,清楚在京师寻得一份张贴布告之差事,既可糊口,亦广交良朋,共商寻宝大业。

某日,清楚在张贴布告时,浆糊不慎落于羊皮卷上,湿透之处,竟现复杂图形……

清楚需要在长度为

n

n

n 个单位的布告板上张贴至多

n

n

n 张布告,第

i

i

i 张布告的长度为

a

i

a_i

ai 个单位,如果选择第

i

i

i 张贴布告时需要满足:

● 第

i

i

i 张布告必须要覆盖掉布告板的第

i

i

i 个位置;

● 布告不能够相互重叠,但是可以紧贴。

清楚想要知道自己按照要求,至少需要张贴几张布告,才能将布告板贴满。

输入描述:

每个测试文件均包含多组测试数据。第一行输入一个整数

T

(

1

T

100

)

T (1≤T≤100)

T(1T100) 代表数据组数,每组测试数据描述如下:

  • 第一行输入一个整数

    n

    (

    1

    n

    5000

    )

    n (1≤n≤5000)

    n(1n5000) 代表布告板的长度(同时也代表布告的张数)。

  • 第二行输入

    n

    n

    n 个整数

    a

    1

    ,

    a

    2

    ,

    ,

    a

    n

    (

    1

    a

    i

    n

    )

    a_1,a_2,…,a_n (1≤a_i≤n)

    a1,a2,,an(1ain) 代表每一张布告的长度。           除此之外,保证所有的

    n

    n

    n 之和不超过

    5000

    5000

    5000

输出描述:

对于每一组测试数据,在一行上输出一个整数代表清楚至少需要贴的布告数量;如果无解,直接输出

1

−1

1

示例1

输入:

2
4
1 2 2 3
3
2 2 2

输出:

2
-1

说明:

对于第一组测试数据,有两种合法的选择方式:
● 贴第一、四张布告;
● 贴第二、三张布告;
对于第二组测试数据,无论怎么张贴都会有重叠部分。

解题思路

本题可转化为带约束的区间覆盖最小化问题,采用动态规划求解。每张布告对应长度固定的区间,放置时必须包含自身序号位置,且区间不可重叠,目标是用最少布告覆盖长度为n的整块布告板。 定义状态 dp[i] 表示覆盖前 i 个单位长度所需的最少布告数,初始 dp[0]=0,其余设为无穷大。对于每个右端点 i,枚举所有布告:若该布告可以 i 为右端点放置(区间包含自身序号且左端点不越界),则通过 dp[i – a[j]] + 1 更新 dp[i] 的最小值,其中 i – a[j] 为该布告左端点的前一位置。最终若 dp[n] 仍为无穷大则无解,否则即为答案。算法时间复杂度

O

(

n

2

)

O(n^2)

O(n2),完全适配题目数据范围。

总结

核心逻辑:将布告的放置约束转化为区间右端点的合法性判断,通过动态规划递推得到覆盖每个长度的最小布告数。 关键操作:定义一维DP状态、枚举右端点与布告完成状态转移、边界越界校验、无穷大初始值处理。 效率保障:平方级复杂度匹配题目n≤5000的约束,总运算量可控,实现简洁直观。

代码简要说明

  • 状态初始化:DP数组初始化为极大值,仅 dp[0] = 0 作为递推边界,表示前0个位置无需布告。
  • 双重循环转移:外层枚举右端点 i(1~n),内层枚举所有布告 j。两个合法性判断:i-j ≤ a[j] 保证区间包含第j+1个序号位置,i – a[j] ≥ 0 保证布告左端点不超出布告板左边界。
  • 最小值更新:合法则用前半段的最优解加1更新当前dp值,始终维护最小布告数。
  • 结果输出:最终判断dp[n]是否仍为无穷大,是则输出-1表示无解,否则输出最小布告数量。
  • 代码内容

    #include <bits/stdc++.h>
    using namespace std;

    #define endl '\\n'
    typedef long long ll;
    typedef unsigned long long ull;
    typedef vector<vector<ll>> vvt;
    typedef pair<ll,ll> pll;
    const ll N=1e3+10;
    const ll INF=1e18;
    const ll M=1e6+10;
    const ll mod=1e9+7;

    using ui=unsigned int;
    using i128=__int128_t;
    using u128=__uint128_t;
    using ld=long double;

    void solve()
    {
    ll n;
    cin>>n;
    vector<ll> a(n,0),dp(n+1,INF);
    for(ll i=0;i<n;i++) cin>>a[i];
    dp[0]=0;
    for(ll i=1;i<=n;i++)
    {
    for(ll j=0;j<i;j++)
    {
    if(ij<=a[j]&&ia[j]>=0)
    {
    dp[i]=min(dp[i],dp[ia[j]]+1);
    }
    }
    }
    if(dp[n]==INF) cout<<1<<"\\n";
    else cout<<dp[n]<<"\\n";
    }

    int main()
    {
    ios::sync_with_stdio(0);
    cin.tie(0),cout.tie(0);
    ll t=1;
    cin>>t;
    while(t) solve();
    return 0;
    }

    赞(0)
    未经允许不得转载:171主机测评 » 清楚姐姐的布告规划【牛客tracker & 每日一题】
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址