Problem A 挑战密室
题目链接:http://nyoj.top/problem/1236
题意:求第一个生成物的分子质量。
思路:字符串模拟,稍微细心一下基本上都能过的。
#include <bits/stdc++.h>
using namespace std;
int i, len;
char str[55];
int Judge() {
int t, wei, cnt, num, ans = 0;
while (i < len && str[i] != '+' && str[i] != ')') {
if (str[i] == '(') {
i = i + 1;
cnt = Judge();
if (isdigit(str[++i])) {
sscanf(str + i, "%d%n", &num, &wei);
i += wei;
cnt *= num;
}
ans += cnt;
}
cnt = 0;
if (str[i] == 'N' && str[i + 1] == 'a')
cnt = 23, i += 2;
else if (str[i] == 'Z' && str[i + 1] == 'n')
cnt = 65, i += 2;
else if (str[i] == 'C' && str[i + 1] == 'a')
cnt = 40, i += 2;
else if (str[i] == 'A' && str[i + 1] == 'l')
cnt = 27, i += 2;
else if (str[i] == 'C' && str[i + 1] == 'l')
cnt = 35, i += 2;
else if (str[i] == 'H')
cnt = 2, i++;
else if (str[i] == 'S')
cnt = 32, i++;
else if (str[i] == 'O')
cnt = 16, i++;
else if (str[i] == 'C')
cnt = 12, i++;
else if (str[i] == 'N')
cnt = 14, i++;
if (isdigit(str[i])) {
sscanf(str + i, "%d%n", &num, &wei);
i += wei;
cnt *= num;
}
ans += cnt;
}
return ans;
}
int main() {
int t, ans;
scanf("%d", &t);
while (t--) {
scanf("%s", str);
len = strlen(str);
for (i = 0; str[i] != '='; i++);
if (isdigit(str[++i])) {
ans = 0;
while (isdigit(str[i]))
ans = ans * 10 + str[i++] - '0';
}
else ans = 1;
ans *= Judge();
printf("%04d\n", ans);
}
return 0;
}
Problem B 最大岛屿
题目链接:http://nyoj.top/problem/1237
题意:1代表陆地,0代表海水,问整个海域的海岛数,以及最大海岛的面积。
思路:简单的深搜,每次找到一个岛,就把这个岛每一个地方都标记上,这样就可以计算出有多少个岛了,找出最大的肯定就简单多了。
#include <bits/stdc++.h>
using namespace std;
int mp[505][505], n, m, p, ans, cnt, max_;
int arr[8][2] = {0, 1, 1, 0, -1, 0, 0, -1, 1, 1, 1, -1, -1, 1, -1, -1};
void DFS(int x, int y) {
cnt++;
int tx, ty;
mp[x][y] = 0;
for (int i = 0; i < 8; i++) {
tx = x + arr[i][0];
ty = y + arr[i][1];
if (tx >= 0 && tx < n && ty >= 0 && ty < m && mp[tx][ty])
DFS(tx, ty);
}
}
int main() {
ans = max_ = 0;
scanf("%d%d%d", &n, &m, &p);
for (int i = 0; i < n; i++)
for (int j = 0; j < m; j++)
scanf("%1d", &mp[i][j]);
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if (mp[i][j]) {
ans++;
cnt = 0;
DFS(i, j);
max_ = max(cnt, max_);
}
}
}
printf("%d %d\n", ans, max_ * p);
return 0;
}
Problem C 最少换乘
题目链接:http://nyoj.top/problem/1238
题意:给你一些BUS线路上的所有站号,求从住处到景点,中间换车的次数最少。
思路:有的题解是用最短路写的,但是我认为等权值的用广搜更快一点,就写了一个广搜的代码。
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 505;
struct edge {
int s, t;
}p, q;
char str[MAXN << 1];
int mp[MAXN][MAXN], vis[MAXN], ans[MAXN], n;
int BFS(int s) {
queue <edge> Q;
Q.push((edge){1, 0});
vis[s] = 1;
while (!Q.empty()) {
p = Q.front();
Q.pop();
for (int i = 1; i <= n; i++) {
if (!vis[i] && mp[p.s][i]) {
vis[i] = 1;
q.s = i;
q.t = p.t + 1;
if (q.s == n)
return p.t;
Q.push(q);
}
}
}
return -1;
}
int main() {
int t, m, k, len;
scanf("%d", &t);
while (t--) {
scanf("%d%d", &m, &n);
memset(mp, 0, sizeof(mp));
memset(vis, 0, sizeof(vis));
while (m--) {
k = 0;
getchar();
scanf("%[^\n]", str);
len = strlen(str);
memset(ans, 0, sizeof(ans));
for (int i = 0; i < len; i++) {
if (isdigit(str[i]))
ans[k] = ans[k] * 10 + str[i] - '0';
else k++;
}
k++;
for (int i = 0; i < k; i++)
for (int j = i + 1; j < k; j++)
mp[ans[i]][ans[j]] = 1;
}
int cnt = BFS(1);
if (cnt != -1)
printf("%d\n", cnt);
else printf("NO\n");
}
return 0;
}
Problem D 引水工程
题目链接:http://nyoj.top/problem/1239
题意:给出自建水库的费用以及从第i个区域到第j个区域引水的费用,求使所有地区都用上水的最小费用。
思路:裸最小生成树,只不过要判断一下,是引水费用小还是自建水库费用小。
#include <bits/stdc++.h>
using namespace std;
const int N = 305;
const int inf = 0x3f3f3f3f;
int minn, n, mp[N][N], vis[N], dis[N], w[N];
int prim(int s) {
int k, sum = w[s];
for (int i = 0; i < n; i++) {
vis[i] = 0;
dis[i] = min(mp[s][i], w[i]);
}
vis[s] = 1;
for (int i = 0; i < n - 1; i++) {
minn = inf;
for (int j = 0; j < n; j++)
if (!vis[j] && dis[j] < minn)
minn = dis[k = j];
vis[k] = 1;
sum += minn;
for (int j = 0; j < n; j++)
if (!vis[j] && dis[j] > mp[k][j])
dis[j] = mp[k][j];
}
return sum;
}
int main() {
int s, t;
scanf("%d", &t);
while (t--) {
s = 0;
scanf("%d", &n);
memset(vis, 0, sizeof(vis));
for (int i = 0; i < n; i++) {
scanf("%d", &w[i]);
if (w[i] < w[s])
s = i;
}
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
scanf("%d", &mp[i][j]);
printf("%d\n", prim(s));
}
return 0;
}
Problem F Distribution
题目链接:http://nyoj.top/problem/1241
题意:给出N个宝藏坐标,然后给出M个画线的交点坐标,输出每次画线后区域(I+III)-(II+IV)的结果。
思路:直接判断就行了。
#include <bits/stdc++.h>
using namespace std;
struct edge {
int x, y;
}e[105];
int main() {
int n, m, x, y;
scanf("%d%d", &n, &m);
for (int i = 0; i < n; i++)
scanf("%d%d", &e[i].x, &e[i].y);
while (m--) {
int a = 0, b = 0;
scanf("%d%d", &x, &y);
for (int i = 0; i < n; i++) {
if (e[i].x > x && e[i].y > y || e[i].x < x && e[i].y < y)
a++;
else b++;
}
printf("%d\n", a - b);
}
return 0;
}
Problem G Interference Signal
题目链接:http://nyoj.top/problem/1242
题意:求连续序列大于等于k个的最大平均值。
思路:数据比较水,直接暴力就完事了,注意输出的时候不要四舍五入。
#include <bits/stdc++.h>
using namespace std;
int main() {
int t, n, m, a[2005];
scanf("%d", &t);
while (t--) {
double sum, max_ = 0;
scanf("%d%d", &n, &m);
for (int i = 0; i < n; i++)
scanf("%d", &a[i]);
for (int i = 0; i <= n - m; i++) {
for (int j = m; j <= n - i; j++) {
sum = 0;
for (int k = i; k < i + j; k++)
sum += a[k];
max_ = max(max_, sum / j);
}
}
printf("%d\n", (int)(max_ * 1000));
}
return 0;
}