競プロ日記

プロコン参加記録とか解いた問題とか

【yukicoder】No.45 回転寿司

yukicoderさんの問題

No.45 回転寿司 - yukicoder

参考書

プログラミングコンテストチャレンジブック [第2版]

難しさ(初心者目線)

・考え方***

・実装***

・面白さ***

ヒント(カーソル合わせると見れます)

コード

#include <algorithm>
#include <cstdio>
#include <iostream>
#include <map>
#include <cmath>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <vector>
#include <stdlib.h>
#include <stdio.h>
#include <bitset>
using namespace std;

#define ll         long long
#define PI         acos(-1.0)
#define FOR(I,A,B) for(int I = (A); I < (B); ++I)

//方針
//N<=10^3なので使うor使わないの愚直に全探索はO(2^N)??なので無理
//動的計画法を用いる
//dp[N+1][use]
//N個目まで調べた時Nを使った時(use=1)の美味しさの和の最大とNを使ってない時(use=0)の最大

int main(){
    int N;
    cin >> N;

    //dp
    int dp[N+1][2];
    FOR(i, 0, N+1) FOR(j, 0, 2) dp[i][j] = -1;
    dp[0][0] = 0;

    //動的計画法
    FOR(i, 0, N){
        int v;
        cin >> v;

        //実際はif必要ない

        //一個前が使用していないなら使ってもいいし使わなくてもいい
        if(dp[i][0]>=0){
            dp[i+1][0] = max(dp[i+1][0], dp[i][0]);
            dp[i+1][1] = max(dp[i+1][1], dp[i][0] + v);
        }

        //一個前が使用してたら次使用しない
        if(dp[i][1]>=0){
            dp[i+1][0] = max(dp[i+1][0], dp[i][1]);
        }
    }
    cout << max(dp[N][0], dp[N][1]) << endl;
}

コメント

動的計画法を用いることでO(N)で解くことができた.
i回目を使わないときはi-1回目に使っていない場合と使っている場合があるどっちかの最大値を用いる.
i回目を使うときはi-1回目に使っていない場合だけという考え方も同じ.