當時在車上,回家之後補的。
a.
從高到底依次列舉硬幣價格判斷即可。
b.
每次從後找一段連續段的0/1的右端點,設位置為 \(pos\),操作其對應的 \(pos + 1\) 次即可。
\(s[pos + 1]\) 與 \(s[pos]\) 相反,所以上次操作後,前面的 \(pos\) 個都為 \(s[pos + 1]\),因此操作 \(pos + 1\) 能把 \([0,pos]\) 全變成 \(s[pos]\)。
最劣情況下需要操作 \(\frac{n(n+1)}{2}\) 次。
程式碼(寫的很醜別噴)
#include<bits/stdc++.h>
using namespace std;
const int N = 1e6 + 7;
struct node {
int a, b;
};
vector<node> v;
int main() {
int n;
string s;
cin >> n >> s;
int ans = 0;
int pos = 0;
for(int i = 0; i < n; i ++) {
if(s[i] == '1') pos = i;
}
int cnt = 0;
int flag = 0;
for(int i = pos; i >= 0; i --) {
if(flag == s[i] - '0') {
continue;
}
flag = s[i] - '0';
v.push_back({i + 1, s[i] - '0'});
ans += i + 1;
}
cout << ans << endl;
for(auto i : v) {
if(i.b == 1) {
for(int j = 1; j <= i.a; j ++) cout << "A";
}
else {
for(int j = 1; j <= i.a; j ++) cout << "B";
}
}
}
c.
即為求從 \((1,1)\) 走到 \((n,n)\) 經過的最少的藍色的數量與從 \((1,n)\) 走到 \((n,1)\) 經過最少的紅色的數量的和。對於這個,可以每個點向周圍四個點連邊,建圖。總點數 \(n^2\),總邊數 \(m = 4n^2\),可以透過。
#include<bits/stdc++.h>
using namespace std;
const int N = 1e6 + 7;
string s[505];
int head[N], ecnt;
int dis[N], vis[N];
struct edge {
int next, to, val;
}e[N];
void addedge(int u, int v, int w) {
e[++ ecnt].to = v;
e[ecnt].next = head[u];
e[ecnt].val = w;
head[u] = ecnt;
}
struct Dis {
int u, val;
friend bool operator < (const Dis a, const Dis b) {
return a.val > b.val;
}
};
void dij(int s) {
priority_queue<Dis> q;
memset(dis, 0x3f, sizeof dis);
dis[s] = 0;
q.push({s, dis[s]});
while(!q.empty()) {
int u = q.top().u;
q.pop();
if(vis[u]) continue;
vis[u] = 1;
for(int i = head[u]; ~i; i = e[i].next) {
int v = e[i].to;
if(dis[v] > dis[u] + e[i].val) {
dis[v] = dis[u] + e[i].val;
q.push({v, dis[v]});
}
}
}
}
int main() {
memset(head, -1, sizeof head);
int n;
cin >> n;
for(int i = 1; i <= n; i ++) {
cin >> s[i];
s[i] = ' ' + s[i];
}
for(int i = 1; i <= n; i ++) {
for(int j = 1; j <= n; j ++) {
if(i == n && j == n) continue;
if(s[i][j] == 'R') {
if(j != n) addedge((i - 1) * n + j, (i - 1) * n + j + 1, s[i][j] != s[i][j + 1]);
if(i != n) addedge((i - 1) * n + j, i * n + j, s[i][j] != s[i + 1][j]);
if(i != 1) addedge((i - 1) * n + j, (i - 2) * n + j, s[i - 1][j] != s[i][j]);
if(j != 1) addedge((i - 1) * n + j, (i - 1) * n + j - 1, s[i][j] != s[i][j - 1]);
}
else {
if(j != n) addedge((i - 1) * n + j, (i - 1) * n + j + 1, s[i][j + 1] != 'R');
if(i != n) addedge((i - 1) * n + j, i * n + j, s[i + 1][j] != 'R');
if(i != 1) addedge((i - 1) * n + j, (i - 2) * n + j, s[i - 1][j] != 'R');
if(j != 1) addedge((i - 1) * n + j, (i - 1) * n + j - 1, s[i][j - 1] != 'R');
}
}
}
dij(1);
int cnt = dis[n * n];
memset(head, -1, sizeof head);
ecnt = 0;
memset(vis, 0, sizeof vis);
for(int i = 1; i <= n; i ++) {
for(int j = 1; j <= n; j ++) {
if(i == n && j == n) continue;
if(s[i][j] == 'B') {
if(j != n) addedge((i - 1) * n + j, (i - 1) * n + j + 1, s[i][j] != s[i][j + 1]);
if(i != n) addedge((i - 1) * n + j, i * n + j, s[i][j] != s[i + 1][j]);
if(i != 1) addedge((i - 1) * n + j, (i - 2) * n + j, s[i - 1][j] != s[i][j]);
if(j != 1) addedge((i - 1) * n + j, (i - 1) * n + j - 1, s[i][j] != s[i][j - 1]);
}
else {
if(j != n) addedge((i - 1) * n + j, (i - 1) * n + j + 1, s[i][j + 1] != 'B');
if(i != n) addedge((i - 1) * n + j, i * n + j, s[i + 1][j] != 'B');
if(i != 1) addedge((i - 1) * n + j, (i - 2) * n + j, s[i - 1][j] != 'B');
if(j != 1) addedge((i - 1) * n + j, (i - 1) * n + j - 1, s[i][j - 1] != 'B');
}
}
}
dij(n);
cout << cnt + dis[(n - 1) * n + 1];
return 0;
}