pair + sort + 棧 2018-6-17 ACM 刷題日記

<Codeforces 988E>   思維

題意:

給一個數,在這個數的各個數位中只能進行它相鄰兩位的互換,問最少經過經過多少次如上操作讓這個數能被25整除。

思路:

由於被25整除的數都有一個性質,那就是末兩位只能是25,50,75,00。所以我的想法是,構造一個後綴ab,看ab是不是以上四種中的某幾種,比如2057,它能構成三種後綴,即25,50,75,顯然75是花費最小的那種。於是我就寫了一個子函數solve如下,各變量和操作註釋得較詳細,這裏不再詳述:

int solve(char a, char b) {
	string t;
	t = s;
	int ln = t.length();
	bool flg1 = 0, flg2 = 0; //判斷能否構成後綴
	int cnt = 0; //計算構成後綴ab的移動步數

	for(int i = ln - 1; i >= 0; i--) { //將最後一位字符置爲b
		if(t[i] == b) {
			flg1 = 1;
			for(int j = i; j < ln - 1; j++) {
				swap(t[j], t[j + 1]);
				cnt++;
			}
			break;
		}
	}

	for(int i = ln - 2; i >= 0; i--) { //將倒數第二位字符置爲a
		if(t[i] == a) {
			flg2 = 1;
			for(int j = i; j < ln - 2; j++) {
				swap(t[j], t[j + 1]);
				cnt++;
			}
			break;
		}
	}

	bool chk = 0; //判斷能否滿足題意
	if(flg1 && flg2) { //能構成後綴ab, 處理前導0
		if(t[0] != '0') chk = 1; 
		else {
			for(int i = 1; i < ln - 2; i++) {
				if(t[i] != '0') {
					cnt += i;
					chk = 1;
					break;
				}
			}
		}
	}
	if(chk) return cnt;
	else return -1;
}

然後用solve加工四個後綴,看有哪幾種能被構成,這裏需要注意一個問題,如果這個數本身就能被25整除,我寫的solve就會返回-1,所以就單獨判一下輸出0就行了。

本人AC代碼:

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <set>
#include <map>
#include <vector>
#include <queue>
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 7;
const int Inf = 1e9 + 7;
string s;

int solve(char a, char b) {
	string t;
	t = s;
	int ln = t.length();
	bool flg1 = 0, flg2 = 0; //判斷能否構成後綴
	int cnt = 0; //計算構成後綴ab的移動步數

	for(int i = ln - 1; i >= 0; i--) { //將最後一位字符置爲b
		if(t[i] == b) {
			flg1 = 1;
			for(int j = i; j < ln - 1; j++) {
				swap(t[j], t[j + 1]);
				cnt++;
			}
			break;
		}
	}

	for(int i = ln - 2; i >= 0; i--) { //將倒數第二位字符置爲a
		if(t[i] == a) {
			flg2 = 1;
			for(int j = i; j < ln - 2; j++) {
				swap(t[j], t[j + 1]);
				cnt++;
			}
			break;
		}
	}

	bool chk = 0; //判斷能否滿足題意
	if(flg1 && flg2) { //能構成後綴ab, 處理前導0
		if(t[0] != '0') chk = 1; 
		else {
			for(int i = 1; i < ln - 2; i++) {
				if(t[i] != '0') {
					cnt += i;
					chk = 1;
					break;
				}
			}
		}
	}
	if(chk) return cnt;
	else return -1;
}

int main() {
	cin >> s;
	int l = s.length();
	ll sum = 0;
	ll tmp = 1;
	for(int i = l - 1; i >= 0; i--) {
		sum += (s[i] - '0') * tmp;
		tmp *= 10;
	}
	if(sum % 25 == 0) {
		puts("0"); return 0;
	}

	int minT = Inf;
	int r1 = solve('2', '5');
	if(r1 != -1) minT = min(r1, minT);

	int r2 = solve('5', '0');
	if(r2 != -1) minT = min(r2, minT);

	int r3 = solve('7', '5');
	if(r3 != -1) minT = min(r3, minT);

	int r4 = solve('0', '0');
	if(r4 != -1) minT = min(r4, minT);
	//cout << r1 << " " << r2 << " " << r3 << " " << r4 << endl;

	if(minT == Inf) puts("-1");
	else cout << minT <<endl;
}

<Codeforces 982B>

 

題意:

一輛車上有n排座位,每排有一個座位,且每排座位長度互不相同,規定每排座位上能且只能坐兩個人,

上車的有A,B兩類人,

A:只挑 沒人的 且座位長度小的 座位坐; B:只挑 有人的 且座位長度大的 座位坐

輸入一個長度爲2 * n 的 01串,0代表A類人,1代表B類人,問根據這個01串輸出這2 * n個人坐在了哪排的座位,保證輸入樣例完全合法。

思路:

根據這些人的上車順序可知,B類人都是和A類人坐在一起的,即AB捆綁,不存在B和B坐在一起這種情況,即會出現 n 對捆綁的 AB 分別坐在這 n 排上。首先根據兩類人上車的順序,再加上AB捆綁,就特別容易想到棧和隊列,這裏我採用 棧模擬 的手段。

先定義一個 pair,不必緊張,我也是做這題現學的pair,我來講下 pair 的作用。

聲明方式:pair <int, int> A[maxn];

是不是和 map 有點像 ~?沒錯,map <int, int> mp,表示兩個關聯的屬性,輸入一個a[i],對應出一個 mp[ a[i] ],因此map又叫做關聯數組,即mp[ a[i] ] 與 a[i] 關聯。pair 其實也是同理,pair 有兩個屬性,first 和 second,和map不同的是,pair 的first 和 second是針對同一個數組的兩個屬性。打個比方,有4張桌子,first表示桌子長度,second表示桌子寬度,first 和 second 都是桌子這個對象的屬性;而 map 是這樣子的一個存在,有四張桌子,記爲a[1] ~ a[4],對於a[1] ~ a[4],每張桌子的價格記爲 mp[a[1]] ~ mp[a[4]]。這樣是不是就理解了很多 ~ 由於pair是針對同一對象的兩個屬性,就可以將pair類比爲結構體來理解。

介紹完pair,說一下針對pair的排序,直接sort的話,就相當於按照默認狀態排序,(與結構體排序不同的是,不必聲明cmp再在sort中調用)而這個默認狀態就是按照first屬性升序排列,如果first屬性相等就按照second屬性升序排。

所以思路就構造出來了,先按身爲first屬性的椅子長度升序排,由於樣例合法,先上來的肯定是A類人,即01串開頭一定是0,初始狀態車上沒人,所以這個最先上來的A類人,一定去找椅子長度最短的座位坐,這也是升序排的理由,然後他坐下以後,就直接打印這排編號就行了,即second屬性,然後壓進棧,接下來如果上來的是A,那就重複以上操作,如果是B,由於棧後進先出,故此時棧頂就是目前被A坐着的,長度最長的椅子的編號,打印編號,捆綁出棧即可。

本人AC代碼:

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <cmath>
#include <set>
#include <map>
#include <ctime>
#include <cctype>
#include <queue>
#include <stack>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxn = 2e5 + 7;
const int Inf = 1e9 + 7;
queue <int> qua;
set <int> sst;
vector <int> vect;
map <int, int> mp;
priority_queue < int, vector<int>, less<int> > qua1;
priority_queue < int, vector<int>, greater<int> > qua2;

int n;
string s;
pair <int, int> A[maxn];
stack <int> stk;

int main() {
	cin >> n;
	for(int i = 1; i <= n; i++) {
		cin >> A[i].first; //first表示椅子長度
		A[i].second = i; //second表示第幾排
	}

	cin >> s;
	int l = s.length();
	sort(A + 1, A + n + 1); //默認按first升序排

	int pos = 1;
	for(int i = 0; i < l; i++) {
		if(s[i] == '0') {
			cout << A[pos].second << " ";
			stk.push(A[pos].second);
			pos++; //角標後移, 因爲內向的人要找沒人的座位就坐
		}
		else {
			cout << stk.top() << " "; //由於棧後進先出, 故棧頂此時就是目前棧內長度最長的那個椅子編號
			stk.pop(); //匹配後出棧
		}
	}
	cout << endl;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章