开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第10天,点击查看活动详情
龍
链接:ac.nowcoder.com/acm/contest…
来源:牛客网
题目描述
三年之期已到,恭迎龍王!!!
龍王自爆身份,开始无尽的复仇,但是长时间的赘婿生活使得他已经忘记了保险箱的密码。
他需要这笔资金来召集手下,于是他找到了你。
你会根据破译密码的难度来收费;
保险柜上会显示一串只包含0和1的数组
你可以进行两种操作:
1.选中数组的一个连续子数组(可以选择整个数组),将其区间翻转( 1110→0111 ),这个操作会收取 a 枚金币。
2.选中数组的一个连续子数组(可以选择整个数组或者一个单独的数字),将子数组里面取反,1 全部变成 0 , 0 全变成 1 ,( 101001→010110 ).这个操作会收取 b枚金币。
当数组里的 0 全变成 1 的时候,保险箱就会打开。
为了尽可能的帮助龍王,你需要使用收取金币最少的方式。
龍王打工四年的积蓄有 x 枚金币,你需要知道龍王是否有能力向你支付开保险箱的报酬,如果能够支付,请打印两行,第一行打印 “ Yes ”,第二行打印龍王剩下的金币。如果不能够,请输出“ No ”。
输入描述:
第一行输入一个 t , t(1≤n≤1×10_3),代表有 t 组数据
每组数据的第一行有 4 个数字 ,n(1≤n≤3×10_5),a,b,x(0≤a,b,x≤1×10_9)
第二行输入长度为 n 的数组
保证所有数组的长度和小于等于3×10_5
输出描述:
如果能够支付,请打印两行,第一行打印“ Yes ”,第二行打印龍王剩下的金币。
如果不能够,请输出“ No ”。
示例1
输入
3
5 1 10 20
01000
5 1 10 10
01000
5 99 99 1
11111
输出
Yes
9
No
Yes
1
思路
想要从0变1,只能借助操作2,可以发现这个题肯定是贪心,贪心的话,要么就是聚集所有的1,然后聚集所有的0,这样就可以用1次操作2来减少代价,否则就所有操作都用操作2。直接比较这两种情况所需的代价,求出最小的代价输出就可以啦。(qwq)
代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define IOS ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
void fun(){
int n,a,b,x;
cin>>n>>a>>b>>x;
string s;
cin>>s;
int cnt=0;
for(int i=0;i<n;i++){
if(s[i]=='0'){
int j=i+1;
while(s[j]=='0'&&j<n)j++;
cnt++;
i=j;
}
}
int ans=min(b*cnt,a*(cnt-1)+b);
if(ans>x)cout<<"No"<<endl;
else cout<<"Yes"<<endl,cout<<x-ans<<endl;
return ;
}
signed main(){
int t;
cin>>t;
while(t--){
fun();
}
return 0;
}