UVa #714 Copying Books (例题8-10)

86 篇文章 0 订阅

最大值最小化,第一反应是Convex Optimization,想起了拉格朗日乘子法和对偶性哈哈哈


Rujia这个不断压低上限的做法,又让我想起了EM算法(其实完全不是一个东西吧)


这道题需要注意几点:

1、书的顺序是不能改变的。

2、RE有可能是因为整型溢出。每道题都必须仔细检查所有可能溢出的地方

3、好好照顾循环的出入口、妥善处理循环跳出后还没有处理的数据(例如归并排序的循环结束后)


Run Time: 0.016s

#define UVa  "LT8-10.714.cpp"
char fileIn[30] = UVa, fileOut[30] = UVa;

#include<cstring>
#include<cstdio>
#include<vector>
#include<algorithm>

using namespace std;


//Global Variables. Reset upon Each Case!
const long long  maxn = 1000;
long long  m, k;
long long  books[maxn];
/

int P(long long x) {
    long long groups = 1;
    long long sum = 0;
    for(long long  i = 0; i < m; i ++) {
        if(books[i] > x) return 0;
        if(sum + books[i] > x) {
            groups ++;
            sum = 0;
        }
        sum += books[i];
    }
    if(sum > x) {
        groups ++;
    }
    if(groups > k) return 0;
    return 1;
}

int main() {

    int N;
    scanf("%d", &N);
    for(int kase = 0; kase < N; kase ++) {
        scanf("%d%d", &m, &k);

        for(long long i = 0; i < m; i ++) scanf("%d", &books[i]);

        long long l = 0;
        long long r = 5000000010L;
        while(l < r) {
            long long mid = l + (r-l)/2;
            if(P(mid)) {
                r = mid;
            }
            else {
                l = mid + 1;
            }
        }

        vector<int> ans[maxn];              //one vector per scriber
        long long sum = 0;
        long long cur_scriber = k-1;
        long long cur_book;
        for(cur_book = m-1; cur_book >= 0; cur_book --) {
            if(sum + books[cur_book] > l) {
                sum = 0;
                cur_scriber --;
            }
            if(cur_book == cur_scriber) {       //one book per scriber.
                for(int i = 0; i <= cur_book; i ++) ans[i].push_back(books[i]);
                break;
            }
            ans[cur_scriber].push_back(books[cur_book]);
            sum += books[cur_book];
        }

        for(long long i = 0; i < k; i ++) {
            for(long long j = ans[i].size()-1; j >= 0; j --) {
                if(j != ans[i].size()-1) printf(" ");
                printf("%d", ans[i][j]);
            }
            if(i!=k-1)printf(" / ");
        }
        printf("\n");
    }
    return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值