SRM643D1Med TheKingsArmyDiv1
大昔に解いてたけど解き直した
問題概要(原文)
$2$ 行 $N(1 \leq N \leq 200)$ 列の文字列がある.文字列は 'S','H' の $2$ 種類の文字からなる.以下の操作を繰り返して,全ての文字が 'H' であるようにしたい.最小何回操作が必要か?不可能なら $-1$ を返せ.
- 隣り合う文字に文字をコピーする
 - ある行のある連続した区間を選んでもう $1$ つの行にコピーする
 - ある列を選んで隣接した列にコピーする
 
考察
自明な考察
- 全て 'S' なら答えは $-1$
 - 全て 'H' なら答えは $0$
 
その他の考察
- 'H' が並んだ行は答えに関係ない.
 - 'S' が並んだ行は列コピーが必要
 - 隣り合った行の文字同士が同じなら縮約できる
 
以上のような考察をすると以下のケースだけ考えればよくなる.
HSHSHSHS...HSHS SHSHSHSH...SHSH少ない方を行コピーでブロック数回かける.のこりはまとめて $1$ 回でできる.
ソースコード
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using Debug = System.Diagnostics.Debug;
using StringBuilder = System.Text.StringBuilder;
public class TheKingsArmyDiv1
{
    public int getNumber(string[] state)
    {
        if (state.SelectMany(x => x).All(x => x == 'S')) return -1;
        if (state.SelectMany(x => x).All(x => x == 'H')) return 0;
        var n = state[0].Length;
        var c = 0; var h = 0;
        var pre = -1;
        for (int i = 0; i < n; i++)
        {
            var k = 0;
            if (state[0][i] != 'S') k |= 1;
            if (state[1][i] != 'S') k |= 2;
            if (k == 0) { c++; continue; }
            if (k == 3) continue;
            if (pre == k) continue;
            pre = k; h++;
        }
        if (h == 0) return c;
        return c + h / 2 + 1;
    }
}
コメント
考察をしてgreedyにやるだけの問題