Codeforces 3B.Lorry(贪心,排序)

明明是一道水题好么。。。

题意是有两种货物,一种占用1单位面积,另一种占用2单位面积

每个货物有对应的价值

现在有n个货物,总面积为v,问如何能够使所载货物价值最大

很明显的背包问题

但是因为要打印路径,感觉直接排序写起来比较方便

我的思路是按不同面积排序,每次比较两种情况的价值,取较大者

我的思路是对的,可能是题目时间太久的原因,莫名其妙地RE

把RE代码贴在这里,希望发现问题的人可以讲解一下:

/* ***********************************************
Author        : yinwoods
E-Mail        : yinwoods@163.com
Created Time  : 2014年12月28日 星期日 16时55分40秒
File Name     : 3B.cpp
************************************************ */

#include <vector>
#include <cmath>
#include <cstdio>
#include <string>
#include <cstring>
#include <iostream>
#include <algorithm>
#define MAXN 200010
#define LL long long
using namespace std;

struct T_T {
    int p, id;
}a1[MAXN], a2[MAXN];

int res[MAXN];

bool cmp(T_T a, T_T b) {
    if(a.p >= b.p) return true;
    return false;
}

int main() {

    memset(a1, 0, sizeof(a1));
    memset(a2, 0, sizeof(a2));

    int n, v, cnt1, cnt2, cnt3, t, p;
    scanf("%d%d", &n, &v);
    cnt1 = cnt2 = cnt3 = 0;
    for(int i=0; i<n; ++i) {
        scanf("%d%d", &t, &p);
        if(t == 1) {
            a1[cnt1].id = i+1;
            a1[cnt1++].p = p;
        } else {
            a2[cnt2].id = i+1;
            a2[cnt2++].p = p;
        }
    }
    sort(a1, a1+cnt1, cmp);
    int ans = 0;
    int j, k;
    j = k = 0;
    sort(a2, a2+cnt2, cmp);

    int last_id = -1;
    int last_cnt3 = -1;


    while(v > 1) {
        if(k >= cnt1) {
            k = cnt1;
            if(j >= cnt2)
                break;
        }

        if(a2[j].p >= a1[k].p+a1[k+1].p) {
            ans += a2[j].p;
            res[cnt3++] = a2[j].id;
            ++j;
            v -= 2;
        } else {
            ans = ans+a1[k].p+a1[k+1].p;
            res[cnt3++] = a1[k].id;
            --v;
            if(k+1 < cnt1) {
                res[cnt3++] = a1[k+1].id;
                last_id = k+1;
                last_cnt3 = cnt3-1;
                k += 2;
                --v;
            } else if(k < cnt1) {
                last_id = k;
                last_cnt3 = cnt3-1;
                ++k;
            }
        }
        //printf("v = %d\tans = %d\n", v, ans);
    }


    //printf("k = %d\n", k);
    //printf("v = %d\n", v);
    if(v && k<cnt1) {
        if(last_id!=-1 && a1[k].p+a1[last_id].p>a2[j].p) {
            ans += a1[k].p;
            res[cnt3++] = a1[k].id;
            --v;
        }
    }
    if(v) {//如果最后还有一个单位空着,考虑是否用一个占用2单位面积的货物来替换
        if(last_id!=-1 && j<cnt2) {
            ans -= a1[last_id].p;
            ans += a2[j].p;
            res[last_cnt3] = a2[j].id;
        }
    }

    printf("%d\n", ans);
    for(int i=0; i<cnt3; ++i)
        printf("%d ", res[i]);
    puts("");

    return 0;
}

可能是数组大小的问题吧,后来看了别人的用STL写了一份代码

如下:

/* ***********************************************
Author        : yinwoods
E-Mail        : yinwoods@163.com
Created Time  : 2014年12月28日 星期日 16时55分40秒
File Name     : 3B.cpp
************************************************ */

#include <vector>
#include <cmath>
#include <cstdio>
#include <string>
#include <cstring>
#include <iostream>
#include <algorithm>
#define MAXN 100010
#define LL long long
using namespace std;


vector< pair<int, int> > a;
vector< pair<int, int> > b;
vector< pair<int, int> > ans;
bool cmp(pair<int, int> x, pair<int, int> y) {
    return x.second > y.second;
}


int main() {

    int n, v, t, p; 
    scanf("%d%d", &n, &v);
    for(int i=0; i<n; ++i) {
        scanf("%d%d", &t, &p);
        if(t == 1) {
            a.push_back(make_pair(i+1, p));
        } else {
            b.push_back(make_pair(i+1, p));
        }
    }

    sort(a.begin(), a.end(), cmp);
    sort(b.begin(), b.end(), cmp);

    int cnt2 = 0;
    while(v>1 && cnt2<b.size()) {
        ans.push_back(b[cnt2]);
        v -= 2;
        ++cnt2;
    }

    int lst = ans.size()-1;
    int cnt1 = 0;
    while(v>0 && cnt1<a.size()) {
        ans.push_back(a[cnt1]);
        --v;
        ++cnt1;
    }

    for(; cnt1<a.size()-1 && lst>=0; cnt1+=2) {
        if(a[cnt1].second + a[cnt1+1].second > ans[lst].second) {
            ans.erase(ans.begin() + lst);
            ans.push_back(a[cnt1]);
            ans.push_back(a[cnt1+1]);
            --lst;
        }
    }

    if(lst >= 0 && cnt1==a.size()-1) {
        if(a[cnt1].second > ans[lst].second) {
            ans.erase(ans.begin() + lst);
            ans.push_back(a[cnt1]);
            --lst;
        }
    }

    if(ans.size() > 0) {
        int res = 0;
        for(int i=0; i<ans.size(); ++i)
            res += ans[i].second;
        printf("%d\n", res);
        for(int i=0; i<ans.size(); ++i) {
            printf("%d ", ans[i].first);
        }
        puts("");
    } else puts("0");

    return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值