chacoderのブログ

競技プログラミングそのほか

1年生 (A First Grader)  第10回日本情報オリンピック 予選4

問題の概要

1桁の数字の羅列(2<=N<100)が与えられ、最後の数字の前に等号(=)を、それ以外の数字と数字の間に(+)か(-)を挿入します。
計算の途中で負になったり20を超えたりする場合はエラーです。等号がなりたつ数を回答します。

入力例

11
8 3 2 4 8 7 2 4 0 8 8

出力例

10

bit全探索で書いてみた

最初、問題文をN<20と勘違いしており、その前提でbit全探索で書いてみました。
当然N<100なのでオーバーフローしました。
小さなケースの部分点20点だけをもらいました。
更にいろいろ考えてみましたがうまい解法を思いつきません。

そもそも1個づつ数える方法では10e9を超えるような場合に間に合うはずがありません。

#include <bits/stdc++.h>
using namespace std;

int main(){
  int N;
  int A[25];
  cin>>N;
  for(int i=0;i<N;i++){
    cin>>A[i];
  }
  
  int ans=A[N-1];
  int ck; 
  long long cnt=0;
  for(int i=0;i<(1<<(N-2));i++){
    //cout<<i<<endl;
    ck=A[0]; 
    for(int j=0;j<N-2;j++){
      if(i & (1<<j)){
        ck+=A[j+1];
      }
      else{
        ck-=A[j+1];
      }
      if(ck<0) break;   
      if(ck>20) break;
    }
    if(ck==ans){
      //cout<<i<<endl;
      cnt++;
    }
  }
  cout<<cnt<<endl;
  return 0;
}

DPで解ける?

解説を見るとDPでうまいこと解けるようです。
自分でも考えてみます。

(to be continued)