NoiminのNoise

競技プログラミング (多め) とWeb (たまに) ,自然言語処理 (ブログではまだ)。数式の書き方を一気に KaTeX に変えようとして記事を全削除してインポートし直すなどしたので,過去にブックマークされた記事は URL が変わってしまっている可能性があります…….

ICPC模擬地区予選2009 B - For the Peace

問題文原文

問題概要

ミサイル保有国がn国ある.それぞれの国はm個のミサイルを保有している.各ミサイルはcapability cをもつ.

各国のミサイルのcapabilityの和の差をd以下に保ったまま,全てのミサイルを廃棄できるかを答えよ.

ただし,各国はミサイルを古いものから順に廃棄しなければならない.

解法概要

除去後のcapabilityの和が最大の国と最小の国の差がd以下になるようなミサイルを貪欲に削除していけばよい. 削除できるミサイルがない場合はNo,全てのミサイルを削除できたらYes.

削除できるミサイルの候補が複数あったら,どのミサイルを削除してもよい.なぜなら,capabilityの和の最大は削除が進むにつれて減りこそすれ増えることはないので,一度削除可能になったミサイルが削除不可能になることはないためである.

ソースコード

#include<cstdio>
#include<vector>
#include<utility>
#include<climits>
#include<algorithm>
 
using namespace std;
 
typedef long long ll;
typedef pair<pair<long, long>, pair<int, int> > P;
 
int main(){
    int n,d;
    while(scanf("%d%d", &n, &d) && n){
        vector<ll> missile[n];
        int m;
        ll min_ = LLONG_MAX, max_ = 1LL;
        bool ans = true;
        for(int i=0;i<n;i++){
            scanf("%d", &m);
            ll c[m], total = 0;
            for(int j=0;j<m;j++){
                scanf("%lld", &c[j]);
                total += c[j];
            }
            missile[i].resize(m+1);
            missile[i][0] = total;
            for(int j=0;j<m;j++) missile[i][j+1] = missile[i][j] - c[m-1-j];
        }
 
        vector<ll> indexes(n, 0);
        while(max_){
            ll mindiff = INT_MAX, diff_i, mindiff_min;
            for(int i=0;i<n;i++){
                if(missile[i][indexes[i]] == 0) continue;
                min_ = INT_MAX;
                max_ = 0LL;
                for(int j=0;j<n;j++){
                    int jj = indexes[j] + ((j==i && missile[j][indexes[j]])?1:0);
                    min_ = min(min_, missile[j][jj]);
                    max_ = max(max_, missile[j][jj]);
                }
                if(max_ - min_ >= 0 && mindiff > max_ - min_){
                    mindiff = max_ - min_;
                    diff_i = i;
                    mindiff_min = min_;
                }
            }
 
            indexes[diff_i]++;
            min_ = mindiff_min;
            max_ = mindiff_min + mindiff;
            if(max_ - min_ > d){
                ans = false;
                break;
            }
        }
 
        printf("%s\n", ans?"Yes":"No");
    }
}

感想

国ごとのミサイルのcapabilityは古いものから順に並んでいるという誤読をしていてつらかった.逆だった.Input / Output もちゃんと全部読もう.

あと,ブログの更新しなかったら実力の伸びが明らかに鈍った感じがする……雑だろうがなんだろうが更新頻度上げよう…….