• 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;
    }
    
  • 相关阅读:
    Python-深浅拷贝
    Python-生成式
    Python-手写web应用
    Python-为什么产生了GIL锁?
    Python-文件处理
    Python-线程
    10大网站设计错误 足以毁掉你的网站【转】
    [转]ASP.NET验证发生前无法调用 Page.IsValid。应在 CausesValidation=True 且已启动回发的控件
    jquery操作字符串常用方法总结及工作代码
    C#中的序列化和反序列化是什么、有什么作用、使用方法详解
  • 原文地址:https://www.cnblogs.com/IzumiSagiri/p/13875273.html
Copyright © 2020-2023  润新知