土下座しながら探索中

主に競技プログラミング

Typical DP Contest I : イウィ

問題リンク :
I: イウィ - Typical DP Contest | AtCoder

問題概要 : 最大iwi数

解法 :
メモ化再帰 => WA
区間DP => TLE
TLEを解消する方法が全く浮かばなかったので諦めてrngさんのコードを参考に解いた

dp[L][R] := 閉区間[L,R]までで得られるiwiの最大値
区間DPでよくやる、長さが小さい順に値を更新をする

コード :

#include<bits/stdc++.h>

#define REP(i,s,n) for(int i=s;i<n;i++)
#define rep(i,n) REP(i,0,n)

using namespace std;

string s;
int dp[301][301];

int main() {
  getline(cin,s);
  int n = s.size();
  REP(length,1,n+1) rep(sp,n-length+1) { // length : 区間の長さ, sp : 左から順に区間の値を更新
    int ep = sp + length - 1;
    REP(k,sp+1,ep) dp[sp][ep] = max(dp[sp][ep],dp[sp][k]+dp[k+1][ep]);
    if( s[sp] == 'i' && s[ep] == 'i' ) {
      REP(k,sp+1,ep) if( s[k] == 'w' ) {
        bool fail = false;
        int len = (k-1)-(sp+1)+1;
        if( len && !( len >= 3 && dp[sp+1][k-1] == len ) ) fail = true;
        len = (ep-1)-(k+1)+1;
        if( len && !( len >= 3 && dp[k+1][ep-1] == len ) ) fail = true;
        if( !fail ) {
          dp[sp][ep] = ep - sp + 1;
          break;
        }
      }
    }
  }
  cout << (int)(dp[0][n-1]/3) << endl;
  return 0;
}