LightOJ 1048 - Conquering Keokradong 【二分】

题目链接:http://www.lightoj.com/volume_showproblem.php?problem=1048

题意:有N 个数,将它们按顺序分成M份,M<=min(N,300)。使得每一份的和的最大值最小。有很多中情况,这些情况中第一天、第二天……的和最大的情况。

思路 : 二分最大的和,得到一个数mid。判断是否符合条件。

代码:(不能AC 实在是找不出来了,先放着)

#include <stdio.h>
#include <ctime>
#include <math.h>
#include <limits.h>
#include <complex>
#include <string>
#include <functional>
#include <iterator>
#include <algorithm>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <list>
#include <bitset>
#include <sstream>
#include <iomanip>
#include <fstream>
#include <iostream>
#include <ctime>
#include <cmath>
#include <cstring>
#include <cstdio>
#include <time.h>
#include <ctype.h>
#include <string.h>
#include <assert.h>

using namespace std;

int a[1010];
int t;
int n, k;
int tmp;
int sum[1010];
int ans;
int g[1010];

int is_ok(int x)
{
    int res;
    int num = 0;
    int pos = 0;

    for (int i = 1; i <= n; i++)
        if (sum[i] - sum[i - 1] > x) return 0;

    for (int i = 1; i <= n; i++)
    {
        if (sum[i] -sum[pos] == x  || (i == n && sum[i] -sum[pos] <= x) || (i != n && sum[i+1] - sum[pos] > x))
        {
            if (i != n) num++;
            pos = i;
        }
    }
    if (num <= k) return 1;
    else return 0;
}

void get_ans()
{
    int res;
    int now = 1;

    int remain = n - k -1;
    while (now <= n)
    {
        int pos = now - 1;
        int tmp = sum[now] - sum[now-1];
        now++;
        if (remain != 0)
        {
            for (; now <= n; now++)
            {
                if (sum[now] - sum[pos] <= ans)
                    tmp = sum[now] - sum[pos], remain --;
                else
                {
                    printf("%d\n",tmp);
                    break;
                }
            }
            if (remain == 0)
            {
                printf("%d\n",tmp);
                now++;
                break;
            }

        }
        else
        {
            printf("%d\n", tmp);
        }

    }
}

int main()
{
    scanf("%d",&t);
    int cases = 1;
    while (t--)
    {
        scanf("%d%d", &n, &k);
        n++;

        int tot = 0;
        memset(sum,0,sizeof(sum));

        for (int i = 1; i <= n; i++)
        {
            scanf("%d", &a[i]);
            sum[i] = sum[i - 1] + a[i];
            tot += a[i];
        }

        int left = 1;
        int right = tot;
        int mid;

        while (left <= right)
        {
            mid = (left + right) / 2;
            if (is_ok(mid))
            {
                ans = mid;
                right = mid - 1;
            }
            else
                left = mid + 1;
        }

        printf("Case %d: ", cases++);
        printf("%d\n", ans);
        get_ans();
    }
    return 0;
}

版权声明:转载请注明出处。

时间: 2024-10-18 12:56:05

LightOJ 1048 - Conquering Keokradong 【二分】的相关文章

1048 - Conquering Keokradong

   PDF (English) Statistics Forum Time Limit: 1 second(s) Memory Limit: 32 MB This winter we are going on a trip to Bandorban. The main target is to climb up to the top of Keokradong. So, we will use a trail. The trail is a continuous marked footpath

LightOJ 1307 Counting Triangles 二分查找

[题解整理]二分题 题目类型: 二分查找: 二分答案. 大致解题思路: 查找注意有序和返回值: 浮点数注意精度: 整数注意返回值,建议另外维护一个变量,用于储存可行解. 题目 分类 传送门 WA点 poj 2785 二分查找 题解 lightoj 1088 二分查找 题解 lightoj 1307 二分查找 题解 longlong poj 2456 整数二分答案 题解 poj 3104 整数二分答案 题解 poj 3258 整数二分答案 题解 poj 3273 整数二分答案 题解 lightoj

Lightoj 1043 - Triangle Partitioning【二分】

题目链接:http://lightoj.com/volume_showproblem.php?problem=1043 题意:一个三角形ABC,DE//BC,已知三角形ADE和四边形BDEC的面积的比,求AD的长度. 解法:二分AD边即可 代码: #include <stdio.h> #include <ctime> #include <math.h> #include <limits.h> #include <complex> #include

Lightoj 1235 - Coin Change (IV) 【二分】

题目链接:http://www.lightoj.com/volume_showproblem.php?problem=1235 题意: 有N个硬币(N<=18).问是否能在每一个硬币使用不超过两次的情况下支付正好K的面额. 思路 : dfs构造出用这些硬币用前一半能支付的全部费用和后一半能支付的全部费用. 之后排序,枚举前一半的每一个面值在第二个里面二分寻找就可以.(或者用set保存). 代码:(set) #include <stdio.h> #include <ctime>

Lightoj 1062 - Crossed Ladders【二分】

题目链接:http://www.lightoj.com/volume_showproblem.php?problem=1062 题意: 两个梯子靠墙放,一个长度是x一个长度是y,它们交点到地面的距离是c.求这两个梯子底部的距离. 思路:二分底部的距离t,往计算t' ,根据t和t'的大小关系更新上下界即可. 设宽为mid,那么可以求得 c/sqrt( y^2 - mid^2 ) + c/sqrt( x^2 - mid ^2 ) = 1 代码: #include <stdio.h> #includ

LightOJ 1088 - Points in Segments 二分

http://www.lightoj.com/volume_showproblem.php?problem=1088 题意:给出N个点,Q个查询,问在区间内的点数有多少个. 思路:直接在线二分,注意边界问题 /** @Date : 2016-12-17-19.03 * @Author : Lweleth ([email protected]) * @Link : https://github.com/ * @Version : */ #include<bits/stdc++.h> #defin

LightOj 1138 - Trailing Zeroes (III) 阶乘末尾0的个数 &amp; 二分

题目链接:http://lightoj.com/volume_showproblem.php?problem=1138 题意:给你一个数n,然后找个一个最小的数x,使得x!的末尾有n个0:如果没有输出impossible 可以用二分求结果,重点是求一个数的阶乘中末尾含有0的个数,一定和因子5和2的个数有关,因子为2的明显比5多,所以我们只需要求一个数的阶乘的因子中一共有多少个5即可; LL Find(LL x) { LL ans = 0; while(x) { ans += x/5; x /=

Lightoj 1127 - Funny Knapsack 【二分】

题目链接:http://www.lightoj.com/volume_showproblem.php?problem=1127 题意:有n个物体(n<30)和一个容量为W的容器,问将容器不装满的放置物品的方式有多少种. 思路 : 状态压缩+二分.将前n/2个物体看做一个整体,将剩下的看做一个整体.1<<(n/2)个状态代表前一半的物品使用情况,然后求出每一种状态的总的体积.排序.对于后面的那一半也是.答案只需枚举一半然后在另一半中找和W差的下界即可. 代码: #include <s

LightOJ 1072 - Calm Down 【二分】

题目链接:http://www.lightoj.com/volume_showproblem.php?problem=1072 解法:考虑角度的关系 二分r 代码: #include <iostream> #include <algorithm> #include <set> #include <map> #include <string.h> #include <queue> #include <sstream> #in