トップページに戻る    次の競技プログラミングの問題へ    前の競技プログラミングの問題へ

No.178 美しいWhitespace (1)

■■■問題■■■

太郎君は難解プログラミング言語である
Whitespaceでプログラムを作ることに熱中しています。
Whitespaceでは、スペース・タブ・改行のみを構文に使用し、その他は無視します。

太郎君はソースコードの美しさにこだわりがあり、
ソースコードについて、すべての行の幅が等しい時に「完璧」と呼びます。

太郎君は自分の書いたWhitespaceのソースコードに全角スペースを挿入することで
「完璧」にしようとしています。

太郎君がソースコードを「完璧」にするために必要な
最小の全角スペースの数を求めるプログラムを作ってください。

ただし、ある行のスペースの数をa、タブの数をb、全角スペースの数をcとしたとき、
その行の幅は(a+4b+2c)とします。

普通のエディタとは異なり、タブの位置などは幅に影響しません。

■■■入力■■■

N
a1 b1
・・・
aN bN

1行目に太郎君が完璧にしたいソースコードの行数Nが与えられます。
続くN行は、ソースコードの行ごとの情報です。i行目にはスペースがai個、タブがbi個あることを表します。

2 <= N <= 1000
0 <= ai,bi <= 1000万
太郎君のソースコードにはスペース・タブ・改行以外の文字は含まれません。
太郎君のソースコードがWhitespaceの文法的に正しいとは限りません。

■■■出力■■■

太郎君がWhitespaceのソースコードを「完璧」にできる時、必要な最小の全角スペースの数を出力してください。
「完璧」にすることが出来ない時、-1を出力してください。
最後に改行してください。 


C#のソース

using System;
using System.Collections.Generic;
using System.Linq;

class Program
{
    static string InputPattern = "Input4";

    static List<string> GetInputList()
    {
        var WillReturn = new List<string>();

        if (InputPattern == "Input1") {
            WillReturn.Add("2");
            WillReturn.Add("1 1");
            WillReturn.Add("3 0");
            //1
            //1行目はスペースが1個、タブが1個なので幅は1+1×4=5です。
            //2行目はスペースが3個、タブは0個なので幅は3+0×4=3です。
            //このままでは「完璧」でないですが、
            //2行目に全角スペースを1個足せば全ての行の幅が5となり「完璧」になるので、1を出力します。
        }
        else if (InputPattern == "Input2") {
            WillReturn.Add("4");
            WillReturn.Add("0 0");
            WillReturn.Add("0 0");
            WillReturn.Add("0 0");
            WillReturn.Add("0 0");
            //0
            //全ての行の幅ははじめから0で、すでに「完璧」です。
            //全角スペースを足す必要はないので、0を出力します。
        }
        else if (InputPattern == "Input3") {
            WillReturn.Add("2");
            WillReturn.Add("0 0");
            WillReturn.Add("1 0");
            //-1
            //1行目の幅は0で、2行目の幅は1です。
            //どのように全角スペースを足しても「完璧」にできないので、-1を出力します。
        }
        else if (InputPattern == "Input4") {
            WillReturn.Add("4");
            WillReturn.Add("30 0");
            WillReturn.Add("20 10");
            WillReturn.Add("10 20");
            WillReturn.Add("0 30");
            //90
        }
        else {
            string wkStr;
            while ((wkStr = Console.ReadLine()) != null) WillReturn.Add(wkStr);
        }
        return WillReturn;
    }

    static void Main()
    {
        List<string> InputList = GetInputList();

        var ResultSet = new List<int>();
        foreach (string EachStr in InputList.Skip(1)) {
            int[] wkArr = EachStr.Split(' ').Select(X => int.Parse(X)).ToArray();
            ResultSet.Add(wkArr[0] + 4 * wkArr[1]);
        }

        //2を法として余りが0の集合
        List<int> Mod0List = ResultSet.FindAll(X => X % 2 == 0);

        //2を法として余りが1の集合
        List<int> Mod1List = ResultSet.FindAll(X => X % 2 == 1);

        //両方とも空集合でない場合
        if (Mod0List.Count > 0 && Mod1List.Count > 0) {
            Console.WriteLine(-1);
            return;
        }

        List<int> WkList = (Mod0List.Count == 0 ? Mod1List : Mod0List);
        int wkMax = WkList.Max();
        long Answer = 0;
        WkList.ForEach(X => Answer += (wkMax - X) / 2);
        Console.WriteLine(Answer);
    }
}


解説

2を法とした余りで分類した集合で考えてます。