一道应该是很简单但我就是TLE的题

 

题目背景

WRITEN BY: NuclearBaseACE

数据生成:NuclearBaseACE

开学了,同学D所在的班换了一名体育老师。

题目描述

现在,新的体育老师不满(︶^︶)上一位体育老师排的队形,于是他先让n名同学站成了一列。

在这一列中,第i位同学的能力值为a[i],体育老师希望将同学分为m组,同时又为了保证课堂中每组之间公平竞争,希望每组同学的能力和尽量小,可是由于同学们都很倔强,同学们都只同意和现在站成的队列位置左右连续相邻的同学分到一组,这让体育老师很头疼班主任要是知道这事,mmp

现在体育老师向在班上大名鼎鼎的你求助,希望了解在这种恶心的情况下每组同学的能力和最小是多少 你不能让体育老师告诉班主任

输入输出格式

输入格式:

第1行包含两个正整数N,M

第2行包含N个空格隔开的非负整数A[i],含义见题目所述。
输出格式:
一个数,即每组同学的能力和最小是多少

说明

对于20%的数据,有N≤10;

对于40%的数据,有N≤1000;

对于100%的数据,有N≤100000,M≤N, A[i]之和不超过10^9。

应该是动态规划思想的一道题,但是时间复杂度O(n^2*m),再看下数据范围,分分钟TLE…

内心是崩溃的…正在找大神解答

附上我的TLE 代码:

#include"stdio.h"
#include"math.h"
#include<algorithm>
using namespace std;
 
int  n,m;
int minn;
int DP[1000029];
int base[1000029];
int main()
{
    scanf("%d%d",&n,&m);
 
    int temp = 0;
    for(int i = 0;i<n; ++i)
    {
        int a = 0;
        scanf("%d", &a);
        temp += a;
        DP[i] = temp;
        base[i] = temp;
    }
    for(int i = 1; i<m-1; ++i)
    {
        for(int j = n-1; j>=0; --j)
        {
            DP[j] = 1e9;
            for(int k = j-1;k>=i-1;--k)
                {
                    DP[j] = min(max(DP[k], base[j]-base[k]),DP[j]);
                    //printf("%d ",temp);
                }
        }//printf("\n");
    }
    //最后一轮只求最后一个数据
    int pos = n-1;
    DP[pos] = 1e9;
    for(int k = n-2;k>=m-2;--k)
    {
        DP[pos] = min(max(DP[k], base[pos]-base[k]),DP[pos]);
    }
 
    printf("%d\n",DP[n-1]);
 
 
 
    return 0;
}

2018-9-24 12:37 更新

标准代码出来了!

没来的及细看,先粘上,之后再写题解思路吧

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<string>
#include<algorithm>
#include<climits>
#include<string>
 
using namespace std;
 
const int maxn=100005;
int n,m,sum,a[maxn];
 
int bin(int lim)
{
    int s=0,cnt=1;
    for(int i=1;i<=n;i++)
    {
        if(a[i]>lim)
            return n;
        if(s+a[i]<=lim)
            s+=a[i];
        else
        {
            s=a[i];
            ++cnt;
        }
    }
    return cnt;
}
int main()
{
//  freopen("x.in","r",stdin);
//  freopen("x.out","w",stdout);
 
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
        sum+=a[i];
    }
    int l = 0,r = sum,tmp,mid;
    while(l<r)
    {
        mid=l+r>>1;
        tmp=bin(mid);
        if(tmp>m)
            l=mid+1;
        else
            r=mid;
    }
    printf("%d\n",l);
    return 0;
}

2018-9-24 14:05 更新

看完答案的我哭了。。。。。。。

简单说下吧,题解根本没用动态规划思想,直接二分答案。

先是取所有总和的一半mid=l+r>>1 ,在bin中函数判断能分成的份数是否能小于要求份数m,如果可以l = mid+1,不可以就直接r = mid, 然后循环,l<r 为循环条件…

原谅我没一开始看时间复杂度和没注意数据范围 ,DP复杂度100000^2*100000分分钟爆炸!

题解复杂度O(nlogn)(应该是吧)

二分答案我记住你了。。。。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值