ABC100D Patisserie ABC

atcoder.jp


問題概要

N種類のケーキはそれぞれ綺麗さx、美味しさy、人気度zのパラメタを持つ。りんごさんはこのケーキをM個違う種類から選ぶことにした。この時、|xの和|+|yの和|+|zの和|の最大値を求めよ。

制約

  • 1 <= N <= 1000
  • -1e10 <= x,y,z<= 1e10

方針・所感

一見すると綺麗さ美味しさ人気度が高い順に選んでいけば貪欲に求められるように見えるが、絶対値を取っているのでどっち方向にいいものを選べばいいかわからないのでここに一工夫がいる。絶対値は正数と負数に場合分けを発生させるものなので、ここを場合分けして、x,y,zの和をそれぞれの正負で場合分けして、合計を求めてしまえばあとは2^3 = 8つの場合それぞれについて貪欲にM個ケーキを選んでしまえば最大値が求まってしまう。

細かいところ・デバッグの記録など

  • 最初それぞれのパラメタについてソートして場合分けすればいいかと思ったが嘘だった。

実装

#include <bits/stdc++.h>
using namespace std;
#define rep(i, nfor(int i = 0; i < n; i++)
typedef long long ll;

int main(){
    ll N, M; cin >> N >> M;
    // P[i][j] := iは-1を綺麗さ・美味しさ・人気度にそれぞれかけるかどうかをbit管理
    // jは何個目かを表し綺麗さ・美味しさ・人気度の合計をもつ
    vector<vector<ll>> P(8vector<ll>(N)) ;

    //入力+データ整理
    rep(i,N){
        ll x, y, z;
        cin >> x >> y >> z;
        rep(j,1 << 3){
            ll t[3= {x, y, z};
            rep(k, 3){
                if(j & 1 << k){
                    t[k] *= -1;
                }
            }
            P[j][i] = t[0+ t[1+ t[2];
        }
    }

    rep(i, 8){
        sort(P[i].begin(), P[i].end(), greater<ll>());
    }

    ll SUM[8= {0};
    rep(i, 8){
        SUM[i] = 0;
        rep(j, M) SUM[i] += P[i][j];
    }
    cout << *max_element(SUM, SUM + 8<< endl;
}