2020ICPC小米 网络选拔赛第一场部分题解

比赛链接:2020ICPC小米 网络选拔赛第一场



A - Intelligent Warehouse

题目要求选择一串连续的数列,使每一个都是上一个的倍数,由于一个数可以存在很多因数,所以选择用动态规划来做。状态转移方程:

[dp[j] = max(dp[i]) + cnt[j],j \% i = 0 ]

#include <iostream>
using namespace std;
#define io_speed_up ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define N 10000000 + 10

int n, tmp, dp[N], cnt[N], ans;

int main() {
	io_speed_up;
	cin >> n;
	for (int i = 1; i <= n; ++i) {
		cin >> tmp;
		cnt[tmp]++;
	}
	for (int i = 1; i <= 10000000; ++i) {
		if (!cnt[i]) {
			continue;
		}
		dp[i] += cnt[i];
		ans = max(ans, dp[i]);
		for (int j = i * 2; j <= 10000000; j += i) {
			dp[j] = max(dp[j], dp[i]);
		}
	}
	cout << ans;
	return 0;
}

B - Intelligent Robot

假设有一堵墙挡在必经之路上,那最短路径一定是从起点径直走向墙的端点再径直走向终点。
所以可以将题目看成是(k)堵墙(2 * k)的端点加上起点和终点共(2 * k + 2)个端点跑最短路。
接下来考虑建边:
如果两点之间的线段与所有墙都没有交点或者交点是墙的两个端点,则这条线段可以建边。
至于判断线段相交,较常见的就是叉乘。这里贴一个大佬的博客

#include <iostream>
#include <cmath>
#include <queue>
#include <iomanip>
using namespace std;
#define io_speed_up ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define INF 0x3f3f3f3f
#define N 610

int n, m, k;
int head[N], cnt;
double dis[N];

struct Point {
	int x, y;
	Point operator - (const Point &p) const {
		return Point{x - p.x, y - p.y};
	}
} wall[N];

struct Node {
	int u;
	double dis;
	bool operator < (const Node &x) const {
		return dis < x.dis;
	}
};

struct Edge {
	int v, next;
	double dis;
} edge[N * N];

void addEdge(int u, int v, double dis) {
	edge[++cnt].v = v;
	edge[cnt].dis = dis;
	edge[cnt].next = head[u];
	head[u] = cnt;
}

int mul(Point p, Point q) {
	int tmp = p.x * q.y - p.y * q.x;
	return tmp < 0 ? -1 : tmp > 0;
}

bool judge(Point p1, Point p2, Point q1, Point q2) {
	int t1 = mul(p2 - p1, q1 - p1);
	int t2 = mul(p2 - p1, q2 - p1);
	int t3 = mul(q2 - q1, p1 - q1);
	int t4 = mul(q2 - q1, p2 - q1);
	return t1 * t2 < 0 && t3 * t4 < 0;
}

bool check(Point p, Point q) {
	for (int i = 1; i <= k; ++i) {
		if (judge(p, q, wall[2 * i - 1], wall[2 * i])) {
			return false;
		}
	}
	return true;
}

double getDis(Point p, Point q) {
	return sqrt((p.x - q.x) * (p.x - q.x) + (p.y - q.y) * (p.y - q.y));
}

void dijkstra() {
	for (int i = 1; i <= 2 * k + 2; ++i) {
		dis[i] = INF;
	}
	priority_queue <Node> q;
	q.push(Node{2 * k + 1, 0});
	dis[2 * k + 1] = 0;
	while (!q.empty()) {
		int u = q.top().u;
		double d = q.top().dis;
		q.pop();
		if (d > dis[u]) {
			continue;
		}
		for (int i = head[u]; i; i = edge[i].next) {
			if (dis[edge[i].v] > dis[u] + edge[i].dis) {
				dis[edge[i].v] = dis[u] + edge[i].dis;
				q.push(Node{edge[i].v, dis[edge[i].v]});
			}
		}
	}
}

int main() {
	io_speed_up;
	cin >> n >> m >> k;
	for (int i = 1; i <= k; ++i) {
		cin >> wall[i * 2 - 1].x >> wall[i * 2 - 1].y;
		cin >> wall[i * 2].x >> wall[i * 2].y;
	}
	cin >> wall[2 * k + 1].x >> wall[2 * k + 1].y;
	cin >> wall[2 * k + 2].x >> wall[2 * k + 2].y;
	for (int i = 1; i <= 2 * k + 2; ++i) {
		for (int j = i + 1; j <= 2 * k + 2; ++j) {
			if (check(wall[i], wall[j])) {
				double len = getDis(wall[i], wall[j]);
				addEdge(i, j, len);
				addEdge(j, i, len);
			}
		}
	}
	dijkstra();
	cout << fixed << setprecision(4);
	cout << dis[2 * k + 2];
	return 0;
}

C - Smart Browser

按顺序对w计数,(1)个w有(1)个/,(n)个w有(2 imes n-1)个/。

#include <iostream>
#include <string>
using namespace std;
#define io_speed_up ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)

int cnt, len, ans;

int main() {
	string s;
	cin >> s;
	len = s.length();
	for (int i = 0; i < len; ++i) {
		if (s[i] == 'w') {
			cnt++;
		} else {
			if (cnt == 1) {
				ans += 1;
			} else if (cnt > 1) {
				ans += 2 * cnt - 1;
			}
			cnt = 0;
		}
	}
	if (cnt == 1) {
		ans += 1;
	} else if (cnt > 1) {
		ans += 2 * cnt - 1;
	}
	cout << ans;
	return 0;
}

I - Walking Machine

对最外面一圈能出去的位置往里进行搜索,标识方向和搜索方向相反则代表可以走出来。

#include <iostream>
using namespace std;
#define io_speed_up ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define N 1000 + 10

const int mod = 1e9 + 7;
char mat[N][N];
int n, m, ans;
bool vis[N][N];
int dx[] = {1, -1, 0, 0};
int dy[] = {0, 0, 1, -1};

void dfs(int x, int y) {
	ans++;
	for (int i = 0; i < 4; ++i) {
		int nxtx = x + dx[i], nxty = y + dy[i];
		if (nxtx >= 1 && nxtx <= n && nxty >= 1 && nxty <= m && !vis[nxtx][nxty]) {
			if (i == 0 && mat[nxtx][nxty] == 'W') {
				vis[nxtx][nxty] = true;
				dfs(nxtx, nxty);
			}
			if (i == 1 && mat[nxtx][nxty] == 'S') {
				vis[nxtx][nxty] = true;
				dfs(nxtx, nxty);
			}
			if (i == 2 && mat[nxtx][nxty] == 'A') {
				vis[nxtx][nxty] = true;
				dfs(nxtx, nxty);
			}
			if (i == 3 && mat[nxtx][nxty] == 'D') {
				vis[nxtx][nxty] = true;
				dfs(nxtx, nxty);
			}
		}
	}
}

int main() {
	io_speed_up;
	cin >> n >> m;
	for (int i = 1; i <= n; ++i) {
		for (int j = 1; j <= m; ++j) {
			cin >> mat[i][j];
		}
	}
	if (!vis[1][1] && (mat[1][1] == 'A' || mat[1][1] == 'W')) {
		vis[1][1] = true;
		dfs(1, 1);
	}
	if (!vis[1][m] && (mat[1][m] == 'D' || mat[1][m] == 'W')) {
		vis[1][m] = true;
		dfs(1, m);
	}
	if (!vis[n][1] && (mat[n][1] == 'A' || mat[n][1] == 'S')) {
		vis[n][1] = true;
		dfs(n, 1);
	}
	if (!vis[n][m] && (mat[n][m] == 'D' || mat[n][m] == 'S')) {
		vis[n][m] = true;
		dfs(n, m);
	}
	for (int i = 2; i <= m - 1; ++i) {
		if (!vis[1][i] && mat[1][i] == 'W') {
			vis[1][i] = true;
			dfs(1, i);
		}
		if (!vis[n][i] && mat[n][i] == 'S') {
			vis[n][i] = true;
			dfs(n, i);
		}
	}
	for (int i = 2; i <= n - 1; ++i) {
		if (!vis[i][1] && mat[i][1] == 'A') {
			vis[i][1] = true;
			dfs(i, 1);
		}
		if (!vis[i][m] && mat[i][m] == 'D') {
			vis[i][m] = true;
			dfs(i, m);
		}
	}
	cout << ans;
	return 0;
}
原文地址:https://www.cnblogs.com/IzumiSagiri/p/13875273.html