1. 程式人生 > >【Codeforces Round #493 (Div. 2) B】Cutting

【Codeforces Round #493 (Div. 2) B】Cutting

ifd main color ble -a 地方 name 次數 include

【鏈接】 我是鏈接,點我呀:)
【題意】


在這裏輸入題意

【題解】


顯然只有在前i個位置奇數偶數出現次數都相同的地方才能切。
(且不管前面怎麽切,這裏都能切的。
那麽就相當於有n個物品,每個物品的代價是|a[i]-a[i-1]|,然後價值是1.
問你不超過B的代價的最大價值是多少。
這就轉化成一個01背包模型了。
或者也可以這麽寫。
\(dp[i][j]表示前i個物品選擇(切)了j個的最小花費\)
然後dp[i][j]=min(dp[i-1][j-1]+cost[i],dp[i-1][j]);//分別表示切第i個與不切第i個。
然後從大到小遍歷一遍dp[n][i];輸出最大的使得dp[n][i]<=B的i就可以了

【代碼】

#include <bits/stdc++.h>

using namespace std;

const int N = 100;
const int INF = 1e8;

//dp[i][j] 前i個位置,cut了j次的最小花費
//dp[i][j] = min(dp[i-1][j-1]+cost[i],dp[i-1][j]);
int dp[N+10][N+10],n,B;
int pre[N+10][2],a[N+10],cost[N+10],cnt;

int main()
{
    #ifdef LOCAL_DEFINE
        freopen("rush.txt","r",stdin);
    #endif // LOCAL_DEFINE
    ios::sync_with_stdio(0),cin.tie(0);
    cin >> n >> B;
    for (int i = 1;i <= n;i++) cin >> a[i];
    for (int i = 1;i <= n;i++){
        for (int j = 0;j < 2;j++) pre[i][j] = pre[i-1][j];
        pre[i][a[i]&1]++;
    }
    for (int i = 1;i <= n-1;i++)
        if (pre[i][0]==pre[i][1]){
            cost[++cnt] = abs(a[i+1]-a[i]);
        }
    n = cnt;
    for (int i = 0;i <= N;i++)
        for (int j = 0;j <= N;j++)
            dp[i][j] = INF;
    dp[0][0] = 0;
    for (int i = 1;i <= n;i++)
        for (int j = 0;j <= i;j++){
            dp[i][j] = dp[i-1][j];//no cut i
            if (j>0){
                dp[i][j] = min(dp[i][j],dp[i-1][j-1]+cost[i]);//cut i
            }
        }
    for (int j = n;j >= 0;j--){
        if (dp[n][j]<=B){
            cout<<j<<endl;
            return 0;
        }
    }
    return 0;
}

【Codeforces Round #493 (Div. 2) B】Cutting