<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;
}