P-6-1. 小朋友上樓梯最小成本

思路

一維陣列讀資料,然後該階扣分加上上一步扣最少的分
再把紀錄存下來就好

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

int n;
int F[100000];
int dp[100000]={-1};
int main(){
    cin>>n;
    for(int i=0; i<n; i++){
        cin>>F[i];
    }
    dp[1] = F[0];
    dp[2] = F[1];
    for(int i=3; i<=n; i++){
        dp[i] = F[i-1] + min(dp[i-2], dp[i-1]);
    }
    cout<<dp[n]<<endl;
    return 0;
}

P-6-2. 不連續的表演酬勞

思路

dp[0] = R[0];
但 dp[1] 要選第一天跟第二天的最大值
然後有分選第 i 天跟不選
如果選第 i 天,根據題目不能選第 i-1 天:R[i] + dp[i-2]
如果不選的話就是 dp[i-1]
紀錄的時候把這兩種情況取最大值

solve.cpp
#include<iostream>
#include<bits/stdc++.h>
using namespace std;
int n;
int R[100000];
int dp[100000]={-1};
int main(){
    cin>>n;
    for(int i=0; i<n; i++){
        cin>>R[i];
    }
    dp[0] = R[0];
    dp[1] = max(R[0], R[1]);
    for(int i=2; i<n; i++){
        dp[i] = max(dp[i-1], dp[i-2] + R[i]);
    }
    cout<<dp[n-1]<<endl;
    return 0;
}

P-6-3. 最小監控鄰居的成本

思路

這裡本來是想跟上一題一樣做法
但後來發現如果假定出選與不選,那後面就都會一直用一開始找到的最小 dp 一直跑下去
所以我們處理 dp[i] 時一定假設第 i 個監視器是裝的
裝了之後會發現需要考慮到 i-1, i-2, i-3,就加上去就好

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

int n;
int cost[100000];
int dp[100000]={-1};
int main(){
    cin>>n;
    for(int i=0; i<n; i++){
        cin>>cost[i];
    }
    dp[0] = cost[0];
    dp[1] = cost[1];
    dp[2] = cost[2] + min(dp[0], dp[1]);
    for(int i=3; i<n; i++){
        dp[i] = cost[i] + min(min(dp[i-1], dp[i-2]), dp[i-3]);
    }
    cout<<min(dp[n-1], dp[n-2])<<endl;
}

Q-6-4. 闖關二選一

思路

因為他有兩個不一樣的選項,所以分dp0跟dp1
首先 dp[0] 都是 c[0][0] 跟 c[0][1] - l
剩下就是dp[i-1]去加上一關跟這關的成本

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

int n, l;
int dp0[100000]={0};
int dp1[100000]={0};
int c[100000][2]={0};
int main(){
    cin>>n>>l;
    for(int i=0; i<n; i++){
        cin>>c[i][0]>>c[i][1];
    }
    dp0[0] = abs(c[0][0]-l);
    dp1[0] = abs(c[0][1]-l);
    for(int i=1; i<n; i++){
        dp0[i] = min(dp0[i-1] + abs(c[i-1][0]-c[i][0]), dp1[i-1] + abs(c[i-1][1]-c[i][0]));
        dp1[i] = min(dp0[i-1] + abs(c[i-1][0]-c[i][1]), dp1[i-1] + abs(c[i-1][1]-c[i][1]));
    }
    cout<<min(dp0[n-1], dp1[n-1])<<endl;
}

Q-6-5. 二維最大子矩陣

思路

開兩個迴圈去定長方形的上下,把每欄總和加起來後去跑dp

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

int m, n;
int a[200][200] = {0};
int ma, ans, r;
int main(){
    cin>>m>>n;
    for(int i=0; i<m; i++){
        for(int j=0; j<n; j++){
            cin>>a[i][j];
        }
    }
    ans = a[0][0];
    for(int t=0; t<m; t++){
        for(int b=t; b<m; b++){
            int sum[200] = {0};
            for(int j=0; j<n; j++){
                for(int i=t; i<=b; i++){
                    sum[j] += a[i][j];
                }
            }
            ma = sum[0];
            r = sum[0];
            for(int i=0; i<n; i++){
                r = max(sum[i], r+sum[i]);
                ma = max(ma, r);
            }
            ans = max(ans, ma);
        }
    }
    cout<<ans<<endl;
    return 0;
}