1. 程式人生 > 其它 >B. Grime Zoo 題解(貪心)

B. Grime Zoo 題解(貪心)

題目連結

題目大意

就是貪心的思路

最優解的一定是:字首的?全部為1/0,字尾的?全部為0/1

根據\(x,y\)的大小來確定字首和字尾的01

然後實現起來發現一個jls的寫法很巧妙,只要記錄數量以及和即可

程式碼

#include<bits/stdc++.h>
#define fi first
#define se second
#define debug cout<<"I AM HERE"<<endl;
using namespace std;
typedef long long ll;
const int maxn=1e5+5,inf=0x3f3f3f3f,mod=1e9+7;
const double eps=1e-6;
char s[maxn];
ll x,y;
ll c0,s0,c1,s1;
signed main(){
    scanf("%s %lld %lld",s+1,&x,&y);
    int n=strlen(s+1);
    if(x>y){
        swap(x,y);
        for(int i=1;i<=n;i++){
            if(s[i]=='0'){
                s[i]='1';
            }else if(s[i]=='1'){
                s[i]='0';
            }
        }
    }
    vector<int> vec;
    for(int i=1;i<=n;i++){
        if(s[i]=='0'){
            c0++;
            s0+=i;
        }else if(s[i]=='1'){
            c1++;
            s1+=i;
        }else if(s[i]=='?'){
            c1++;
            s1+=i;
            vec.push_back(i);
        }
    }
    ll ans=1e18;
    for(int i=0;i<vec.size();i++){
        ans=min(ans,(s1-c1*(c1+1)/2)*x+(s0-c0*(c0+1)/2)*y);
        c0++,c1--;
        s0+=vec[i],s1-=vec[i];
    }
    ans=min(ans,(s1-c1*(c1+1)/2)*x+(s0-c0*(c0+1)/2)*y);
    printf("%lld\n",ans);
    return 0;
}


卷也卷不過,躺又躺不平