Codeforces Round #493 (Div. 2) ---- B Cutting

    这题问我们有没有这样的一种切割满足所有的分割段都是奇偶数个数相等,然后切割的个数最大不能超过我们给的B个币。

    因为每一段都要满足奇数和偶数,那么我们从开始的每一个点遍历,统计所有奇数的个数和偶数的个数,每当两个个数相同的地方,表示这个地方可以作一次切割,那么如果遍历完了 ,没有做切割,或者是最后的奇偶数个数不同,代表没有合法的分割。

    而如果有合法的分割的话,那么我们就可以有,所有的分割,每个有一个权重,每个拿和不拿两种情况,求怎么拿,拿到的分割个数最大。这个是一个典型的01背包问题,我们可以采取01背包的方式去求解,但是我们也发现,每一个分割对答案的价值贡献都是1,那么等价值的情况下我们当然优先拿最小价值的分割,这样贪心一定可以拿到最多。注意价值是取绝对值。

代码如下,01背包和贪心

#include <bits/stdc++.h>
using namespace std;
int a[105],c[105];
int dp[105],w[105];
int main(){
    int n,b;
    cin >> n >> b;
    for (int i=0; i<n; i++) {
        cin >> a[i];
    }
    int cnt1 = 0,cnt2 = 0,k = 1;
    for (int i=0; i<n; i++) {
        if (a[i] & 1) {
            cnt1++;
        }else{
            cnt2++;
        }
        if (cnt1 == cnt2 && i != n-1) {
            w[k++] = abs(a[i+1]-a[i]);
        }
    }
    if (cnt1 != cnt2 || k == 1) {cout << 0 << endl; return 0;}
//    sort(w+1, w+k+1);
//    int ans = 0,cnt = 0;
//    for (int i=1; i<k; i++) {
//        cnt += w[i];
//        cout << w[i] << endl;
//        if (cnt <= b) {
//            ans++;
//        }else{
//            break;
//        }
//    }
 //   cout << ans << endl;
    for (int i=1; i<k; i++) {
        for (int j=b; j>=1; j--) {
            if (j >= w[i]) {
               // cout << j << ' ' << w[i] << endl;
                dp[j] = max(dp[j] , dp[j-w[i]]+1);
            }
        }
    }
    cout << dp[b] << endl;
    return 0;
}


猜你喜欢

转载自blog.csdn.net/CCCCTong/article/details/81060349