codeforces Round #681 (Div. 2) 1443B Saving the City

immortal_luo發表於2020-11-04
題目連結

在這裡插入圖片描述

題目翻譯:

Bertown是一個由n個建築組成的城市,且這n個城市成一條直線。
城市的保安部門發現一些建築下面有炸彈。有一張地圖可以顯示哪些建築下面有炸彈,該地圖是一個長度為n的字串,如果第 i 個字元是 “1” ,這表示第 i 個建築下面有炸彈,如果是 “0” ,表示第 i 個建築下面沒有炸彈。
Bertown最厲害的士兵知道怎麼在不毀壞建築的前提下引爆炸彈。當第x個建築下面的炸彈被引爆時,將會引爆相鄰的兩個建築(x - 1和x + 1)下面的炸彈(如果相鄰的建築下面沒有炸彈,就不會發生什麼)。因此,只要引爆一段連續的炸彈中的任意一個炸彈,就足以引爆這一整段連續的炸彈。引爆一顆炸彈,需要花費a個硬幣,你可以執行任意多次這樣的操作。
你也可以在一個沒有炸彈的建築下面放置一個炸彈,這需要花費b個硬幣,你也可以執行任意多次這樣的操作。
你可以以任意順序執行上面的操作。
你想要引爆所有的炸彈,計算最少需要花費多少硬幣。

解題思路:

對於一段連續的炸彈,有兩種選擇:直接引爆或者連線別的炸彈,再一起爆炸。比如“00111000110”,a=5,b=1時,如果兩段炸彈各自引爆,需要花費5+5=10個硬幣。如果連線後再引爆,需要花費3+5=8個硬幣,顯然後者的選擇更省錢。因此可以得出結論,如果兩段炸彈之間的距離*b≤a,則連線後引爆,否則直接引爆。
我們可以指定引爆第一段連續的炸彈,而第二段炸彈如何引爆取決於其與前一段炸彈之間的距離,之後同樣的道理。

程式碼:
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
#include<vector>
#include<map>
#include<queue>
#include<cstdio>
#include<cmath>
#define inf 0x3f3f3f3f
using namespace std;
vector<long long>v;
int main() {
//	freopen("1.txt","r",stdin);
	long long t,a,b,c;
	string s;
	cin>>t;
	while(t--) {
		cin>>a>>b>>s;
		v.clear();
		long long flag=1,cnt=0,l=s.size(),r=-1,sum=0;
		for(int i=0; i<s.size(); i++) {
			if(s[i]=='1') {
				l=i;
				break;
			}
		}
		for(int i=s.size()-1; i>=0; i--) {
			if(s[i]=='1') {
				r=i;
				break;
			}
		}
		if(l==s.size()||r==-1) {
			cout<<0<<endl;
			continue;
		}
		for(int i=l; i<=r; i++) {
			c=s[i]-'0';
			if(c==flag) {
				cnt++;
			} else {
				if(flag==0) {
					if(cnt*b<=a) {
						sum+=cnt*b;
					} else {
						sum+=a;
					}
				}
				flag=flag?0:1;
				cnt=1;
			}
		}
		sum+=a;
		cout<<sum<<endl;
	}
	return 0;
}
總結:

開始一直以為是動態規劃之類的,沒想到還挺簡單的,被唬住了。

相關文章