LIGHTOJ 1048 Conquering Keokradong 二分好题

寒假做了不少二分和二分图(没啥联系偷笑),当时懒得没有写报告,现在感觉都忘了,正好今天补考完,。。。。狂补orz

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

1048 - Conquering Keokradong
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 that goes from Bandorban to Keokradong.

Part of the experience is also the route planning of the trip. We have a list of all possible campsites that we can use along the way and we want to do this trip so that we only stop K nights to camp. We also know in advance the distance between consecutive campsites and we are only allowed to camp at a campsite. Our goal is to plan the trip so that we minimize the maximum amount of walking done in a single day. In other words, if our trip involves 2 nights (3 days of walking), and we walk 9, 10, 5 miles on each day respectively, the cost (maximum amount of walking done in one day) is 10. Another schedule that involves walking 9, 6, 9 miles on each day has cost 9.

Given the distances between N consecutive campsites of a trail and given the number of nights for your trip, K, your task is to devise a camping strategy for the specified trail such that it minimizes the maximum amount of walking done in a single day. Note that the first distance value given is the distance from our start-point of the trail to our 1st campsite, and the last distance value given is the distance from our Nth campsite to our end-point of the trail.

Input

Input starts with an integer T (≤ 200), denoting the number of test cases.

Each case contains of two integers, the number of campsites, N (1 ≤ N ≤ 1000) and the number of nights of the trip, K (1 ≤ K ≤ min(N, 300)). The following N + 1 lines indicate the distance in miles between consecutive campsite locations. All the integers will be positive and less than 10000.

Output

For each case of input you have to print the case number and the minimized cost as described above. Then print K+1 lines, each containing the amount of distance covered in ith day. As there can be many solutions, the primary target is to find the one which ensures that each day we have to walk some distance. For ties, print the one where the distance covered in first day is maximum, then the distance covered in second day is maximum and so on.

Sample Input

Output for Sample Input

1

4 3

7

2

6

4

5

Case 1: 8

7

8

4

5

回想下题目意思大概是:给你n+1个数让你变成k+1个数,(通过相邻的数相加),然后问你这k+1个数中最大值最小是多少,。

思路:看到最小化最大值会很容易想到二分答案,二分的时候肯定用贪心的思想,这道题坑的地方在于要输出值!!输出的时候有些细节要注意,比如最后要满足输出的是n+1个数,这就不能简单的用贪心一直输出完,需要再加判断下,现在回想起来依旧觉得恶心,代码如下:

/**
 * @author neko01
 */
//#pragma comment(linker, "/STACK:102400000,102400000")
#include <cstdio>
#include <cstring>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <math.h>
using namespace std;
typedef long long LL;
#define INF 100000000
const double pi=acos(-1.0);
const double eqs=1e-10;
int a[1001];
int n,k;
bool gao(int x)
{
    int sum=0,s=0;
    for(int i=0;i<n;i++)
    {
        if(a[i]>x)
            return false;
        s+=a[i];
        if(s>x)
        {
            sum++;
            s=a[i];
            if(sum>k)
                return false;
        }
    }
    sum++;  //the final number
    if(sum<=k)
        return true;
    return false;
}
void print(int x)
{
    int s=0,sum=0,j;
    for(int i=0;i<n;i++)
    {
        s+=a[i];
        if(s>x)
        {
            printf("%d\n",s-a[i]);
            s=a[i];
            sum++;
        }
        if(k-sum==n-i)
        {
            printf("%d\n",s);
            for(i++;i<n;i++)
                printf("%d\n",a[i]);
        }
    }
}
int main()
{
    int T,cnt=0;
    scanf("%d",&T);
    while(T--)
    {
        int ans=0,l=INF,r=0;
        scanf("%d%d",&n,&k);
        k++,n++;
        for(int i=0;i<n;i++)
        {
            scanf("%d",&a[i]);
            l=min(l,a[i]);
            r+=a[i];
        }
        while(l<=r)
        {
            int mid=(l+r)/2;
            if(gao(mid))
            {
                ans=mid;
                r=mid-1;
            }
            else
                l=mid+1;
        }
        printf("Case %d: %d\n",++cnt,ans);
        print(ans);
    }
    return 0;
}

还有道姊妹题,http://lightoj.com/volume_showproblem.php?problem=1076 lightoj1076,所幸的是这道不用输出每个结果,就简单多了。,

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值