zoukankan      html  css  js  c++  java
  • 2020杭电多校第四场题解

    2020 Multi-University Training Contest 4


    施工中。。。

    1002 Blow up the Enemy

    签到题,只需要计算每把武器造成至少100伤害的时间,求出最少时间武器的数量,然后计算胜率即可。

    比赛时一发过。

    #include<bits/stdc++.h>
    #define ll long long
    #define maxn 100010
    #define mod 1000000007
    using namespace std;
    int main() {
    	int t;
    	scanf("%d", &t);
    	while (t--) {
    		int n;
    		scanf("%d", &n);
    		int sum = 0, ma = 1e9;
    		for (int i = 0; i < n; i++) {
    			int x, y;
    			scanf("%d%d", &x, &y);
    			int tp = ((100 + x - 1) / x - 1) * y;
    			if (tp < ma) ma = tp, sum = 1;
    			else if (tp == ma) sum++;
    		}
    		printf("%.8lf
    ", 1.0 - 0.5 * sum / n);
    	}
    	return 0;
    }
    

    1003 Contest of Rope Pulling

    题目看上去像是一个背包问题,但如果使用朴素的背包方法会T。

    所以可以将物品的容量分为正负两种,依次进行背包操作,答案保持在0处。

    由于物品大小不大,所以对数组进行随机排序,缩小背包的大小,答案正确率处于很高水平。

    最后一小时尝试过,使用按大小排序方式不行,然后随机排序后就过了,只能说是运气好。

    #include<bits/stdc++.h>
    #define ll long long
    #define maxn 300010
    #define mod 1000000007
    using namespace std;
    ll dp[maxn];
    ll inf = -1e15;
    struct cv {
    	ll x, y;
    }a[maxn], b[maxn], c[maxn];
    bool cmp(cv p, cv q) {
    	return p.y > q.y;
    }
    int main() {
    	int t;
    	scanf("%d", &t);
    	while (t--) {
    		int n, m;
    		scanf("%d%d", &n, &m);
    		for (int i = 0; i < n; i++) scanf("%lld%lld", &a[i].x, &a[i].y);
    		for (int i = 0; i < m; i++) scanf("%lld%lld", &b[i].x, &b[i].y);
    		random_shuffle(a, a + n);
    		random_shuffle(b, b + m);
    		int cnt = 0;
    		for (int i = 0; i < min(n, m); i++) {
    			c[cnt++] = a[i];
    			b[i].x *= -1;
    			c[cnt++] = b[i];
    		}
    		if (n > m) for (int i = m; i < n; i++) c[cnt++] = a[i];
    		else for (int i = n; i < m; i++) {
    			b[i].x *= -1; c[cnt++] = b[i];
    		}
    		for (int i = 0; i < maxn; i++) dp[i] = inf;
    		dp[maxn / 2] = 0;
    		for (int i = 0; i < cnt; i++) {
    			if (c[i].x > 0) {
    				for (ll j = maxn - 1; j - c[i].x >= 0; j--) {
    					dp[j] = max(dp[j], dp[j - c[i].x] + c[i].y);
    				}
    			}
    			else {
    				for (ll j = 0; j - c[i].x < maxn; j++) dp[j] = max(dp[j], dp[j - c[i].x] + c[i].y);
    			}
    		}
    		printf("%lld
    ", dp[maxn / 2]);
    	}
    	return 0;
    }
    

    1004 Deliver the Cake

    求最短路的模板题,在计算距离的时候处理一下是左手还是右手拿蛋糕就可以了。

    由于中途转换过程处理出了一些问题导致WA2,想清楚后就解决了。

    #include<bits/stdc++.h>
    #define ll long long
    #define maxn 200010
    #define mod 1000000007
    using namespace std;
    vector<int>b[maxn];
    vector<ll>c[maxn];
    char a[maxn];
    int pe[maxn];
    ll ans[maxn][3];
    struct cv {
    	int x, pe;
    	ll y;
    	friend bool operator<(cv p, cv q) {
    		return p.y > q.y;
    	}
    }dd, bb;
    int main() {
    	int t;
    	scanf("%d", &t);
    	while (t--) {
    		int n, m, s, e;
    		ll x;
    		scanf("%d%d%d%d%lld", &n, &m, &s, &e, &x);
    		scanf("%s", a + 1);
    		for (int i = 1; i <= n; i++) {
    			if (a[i] == 'L') pe[i] = 1;
    			else if (a[i] == 'R') pe[i] = 2;
    			else pe[i] = 3;
    			vector<int>v;
    			swap(v, b[i]);
    			vector<ll>vv;
    			swap(vv, c[i]);
    			ans[i][1] = ans[i][2] = 0;
    		}
    		for (int i = 0; i < m; i++) {
    			int l, r;
    			ll z;
    			scanf("%d%d%lld", &l, &r, &z);
    			b[l].push_back(r);
    			c[l].push_back(z);
    			b[r].push_back(l);
    			c[r].push_back(z);
    		}
    		dd.x = s, dd.y = 0;
    		priority_queue<cv>q;
    		if (pe[s] & 1) {
    			dd.pe = 1;
    			q.push(dd);
    		}
    		if (pe[s] & 2) {
    			dd.pe = 2;
    			q.push(dd);
    		}
    		while (!q.empty()) {
    			dd = q.top();
    			q.pop();
    			int now = dd.x;
    			if (dd.y != ans[now][dd.pe]) continue;
    			if (now == e) break;
    			for (int i = 0; i < b[now].size(); i++) {
    				bb.x = b[now][i], bb.y = dd.y + c[now][i];
    				if ((dd.pe & pe[bb.x]) == 0) {
    					bb.pe = pe[bb.x];
    					bb.y += x;
    				}
    				else bb.pe = dd.pe;
    				if (ans[b[now][i]][bb.pe] == 0) {
    					ans[b[now][i]][bb.pe] = bb.y;
    					q.push(bb);
    				}
    				else if (ans[b[now][i]][bb.pe] > bb.y) {
    					ans[b[now][i]][bb.pe] = bb.y;
    					q.push(bb);
    				}
    			}
    		}
    		if (ans[e][1] == 0) printf("%lld
    ", ans[e][2]);
    		else if (ans[e][2] == 0) printf("%lld
    ", ans[e][1]);
    		else printf("%lld
    ", min(ans[e][1], ans[e][2]));
    	}
    	return 0;
    }
    

    1005 Equal Sentences

    对于每个相邻字符不同的串,相邻的两个数可以交换,但是不能连续交换

    通过 (dp) 可以得到,不同的串的个数就是斐波那契数列

    计算的时候,连续相同的数阶段截断即可

    比赛时一发过。

    #include<bits/stdc++.h>
    #define ll long long
    #define maxn 200010
    #define mod 1000000007
    using namespace std;
    int a[maxn];
    ll dp[maxn];
    int main() {
    	ios::sync_with_stdio(false);
    	cin.tie(nullptr); cout.tie(nullptr);
    	int t;
    	cin >> t;
    	dp[0] = 1;
    	dp[1] = 1;
    	for (int i = 2; i < maxn; i++) {
    		dp[i] = dp[i - 1] + dp[i - 2];
    		dp[i] %= mod;
    	}
    	while (t--) {
    		int n;
    		map<string, int>mp;
    		int cnt = 0;
    		cin >> n;
    		for (int i = 1; i <= n; i++) {
    			string tp;
    			cin >> tp;
    			if (mp.count(tp)) a[i] = mp[tp];
    			else {
    				mp[tp] = cnt;
    				a[i] = cnt++;
    			}
    		}
    		ll ans = 1;
    		ll sum = 1;
    		for (int i = 2; i <= n; i++) {
    			if (a[i] == a[i - 1]) {
    				ans = ans * dp[sum] % mod;
    				sum = 1;
    			}
    			else sum++;
    		}
    		ans = ans * dp[sum] % mod;
    		printf("%lld
    ", ans);
    	}
    	return 0;
    }
    

    1007 Go Running

    对于每条记录,我们令他都是有一个从 (t=0) 的时刻就开始跑的人经过的,那这个人可以同时经过的点都是最多的

    对于每条记录,可能会有两个人,即一个从东向西跑,一个从西向东跑

    我们对两个人建边,就可以建成一个二分图

    对于每条边都需要一条个点,即最小点覆盖

    原先用贪心思想WA了一发,使用不太靠谱的模板T了一发,模板改错又WA了一发,最后发现问题才过了。

    #include<bits/stdc++.h>
    #define ll long long
    #define mod 1000000007
    using namespace std;
    
    const int MAXN = 200010;
    const int MAXM = 200010;
    const int INF = 2147483647;
    struct Edge {
    	int v;
    	int next;
    } edge[MAXM];
    
    
    int nx, ny;
    int cnt;
    int t;
    int dis;
    
    int first[MAXN];
    int xlink[MAXN], ylink[MAXN];
    /*xlink[i]表示左集合顶点所匹配的右集合顶点序号,ylink[i]表示右集合i顶点匹配到的左集合顶点序号。*/
    int dx[MAXN], dy[MAXN];
    /*dx[i]表示左集合i顶点的距离编号,dy[i]表示右集合i顶点的距离编号*/
    int vis[MAXN]; //寻找增广路的标记数组
    
    void init() {
    	cnt = 0;
    	memset(first, -1, sizeof(first));
    	memset(xlink, -1, sizeof(xlink));
    	memset(ylink, -1, sizeof(ylink));
    }
    
    void read_graph(int u, int v) {
    	edge[cnt].v = v;
    	edge[cnt].next = first[u], first[u] = cnt++;
    }
    
    int bfs() {
    	queue<int> q;
    	dis = INF;
    	memset(dx, -1, sizeof(dx));
    	memset(dy, -1, sizeof(dy));
    	for (int i = 0; i < nx; i++) {
    		if (xlink[i] == -1) {
    			q.push(i);
    			dx[i] = 0;
    		}
    	}
    	while (!q.empty()) {
    		int u = q.front();
    		q.pop();
    		if (dx[u] > dis) break;
    		for (int e = first[u]; e != -1; e = edge[e].next) {
    			int v = edge[e].v;
    			if (dy[v] == -1) {
    				dy[v] = dx[u] + 1;
    				if (ylink[v] == -1) dis = dy[v];
    				else {
    					dx[ylink[v]] = dy[v] + 1;
    					q.push(ylink[v]);
    				}
    			}
    		}
    	}
    	return dis != INF;
    }
    
    int find(int u) {
    	for (int e = first[u]; e != -1; e = edge[e].next) {
    		int v = edge[e].v;
    		if (!vis[v] && dy[v] == dx[u] + 1) {
    			vis[v] = 1;
    			if (ylink[v] != -1 && dy[v] == dis) continue;
    			if (ylink[v] == -1 || find(ylink[v])) {
    				xlink[u] = v, ylink[v] = u;
    				return 1;
    			}
    		}
    	}
    	return 0;
    }
    
    int MaxMatch() {
    	int ans = 0;
    	while (bfs()) {
    		memset(vis, 0, sizeof(vis));
    		for (int i = 0; i < nx; i++) if (xlink[i] == -1) {
    			ans += find(i);
    		}
    	}
    	return ans;
    }
    
    int main() {
    	int tt;
    	scanf("%d", &tt);
    	while (tt--) {
    		init();
    		int n;
    		scanf("%d", &n);
    		map<ll, int>mp1, mp2;
    		int cntt = 0;
    		set<ll>mep;
    		for (int i = 0; i < n; i++) {
    			ll x, y;
    			scanf("%lld%lld", &x, &y);
    			ll tu = x * (1e9 + 1) + y;
    			if (mep.count(tu)) continue;
    			else mep.insert(tu);
    			ll id1, id2;
    			if (mp1.count(x - y)) id1 = mp1[x - y];
    			else {
    				mp1[x - y] = cntt;
    				id1 = cntt;
    				cntt++;
    			}
    			if (mp2.count(x + y)) id2 = mp2[x + y];
    			else {
    				mp2[x + y] = cntt;
    				id2 = cntt;
    				cntt++;
    			}
    			read_graph(id1, id2);
    		}
    		nx = cntt; ny = cntt;
    		int ans = MaxMatch();
    		printf("%d
    ", ans);
    	}
    	return 0;
    }
    

    1011 Kindergarten Physics

    由于万有引力太小,可以忽略不记,直接输出原距离即可。

    比赛时一发过。

    #include <bits/stdc++.h>
    #define db double
    using namespace std;
    const db g = 6.67430 * 1e-11;
    
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(nullptr); cout.tie(nullptr);
        int t; cin >> t;
        while (t--) {
            db a, b, d, t;
            cin >> a >> b >> d >> t;
            cout << d << '
    ';
        }
        return 0;
    }
    

    1012 Last Problem

    构造题,对于每个数字写下之前保证周围有比它小1-4的数字,所以考虑递归先放小的数字。

    同时记录小每个位置的数字,如果已经放上了要求的数,便无需再填写。

    比赛时一发过。

    #include<bits/stdc++.h>
    #define ll long long
    #define maxn 300010
    #define mod 1000000007
    using namespace std;
    int a[2000][2000];
    int to[4][2] = { 0,-1,1,0,-1,0,0,1 };
    void sol(int n, int x, int y) {
    	for (int i = 0; i < 4; i++) {
    		if (a[x + to[i][0]][y + to[i][1]] == n - i - 1) continue;
    		if (n - i - 1 >= 1) sol(n - i - 1, x + to[i][0], y + to[i][1]);
    	}
    	printf("%d %d %d
    ", x, y, n);
    	a[x][y] = n;
    }
    int main() {
    	int n;
    	scanf("%d", &n);
    	sol(n, 1000, 1000);
    	return 0;
    }
    
  • 相关阅读:
    [原]关于在Python和C#之间消息传递的问题
    【原】为DevExpress的ChartControl添加Y轴控制 和 GridControl中指定列添加超级链接
    【原】使用Json作为Python和C#混合编程时对象转换的中间文件
    【原】在Matplotlib绘图中添加Latex风格公式
    【原】关于AdaBoost的一些再思考
    【原】使用Tkinter绘制GUI并结合Matplotlib实现交互式绘图
    使用C#+Linq+SQL快速开发业务
    oracle expdp导出时报 ora-39070:无法打开日志文件
    Oracle 关于expdp和impdp的应用实践
    IIS7启动优化
  • 原文地址:https://www.cnblogs.com/st1vdy/p/13410023.html
Copyright © 2011-2022 走看看