2020百度之星程序设计大赛初赛二
A. Poker (Hdu 6775)
题目大意
给定n个币,每次投至少m个,当投个时,给回。问你最多能投多少次。
解题思路
很显然每次投元是最优的,因为但凡投元,给回的钱数不可能会增加二,要不不变要不减少。
每次投减少个币,先算出可以减少多少次,记为次,剩余个币。
因为是给个币返回个,我们要倒推回去次,找到那一点,恰好满足
即
所以
最终答案就是。
(代码是考虑小于号的情况)
神奇的代码
#include <bits/stdc++.h> using namespace std; typedef long long LL; int main(void) { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); int t; cin >> t; while (t--) { int n, m, p; cin >> n >> m >> p; if (n < m) { cout << 0 << endl; continue; } int qwq = m - m * (100 - p) / 100; int cnt = n / qwq; n %= qwq; cnt -= (m - n) / qwq; if ((m - n) % qwq == 0) ++cnt; cout << cnt << endl; } return 0; }
B. Distance (Hdu 6776)
题目大意
告诉你个人距离你的距离,问这个人俩俩距离和最小值是是多少。
解题思路
很容易发现距离和最小就是这个人位于同一条直线且位于你的同一边,计算俩相邻人之间的距离对答案的贡献即可。
神奇的代码
#include <bits/stdc++.h> using namespace std; typedef long long LL; int main(void) { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); int kase; cin >> kase; for (int ii = 1; ii <= kase; ii++) { int n; cin >> n; vector<LL> qwq(n); for (int i = 0; i < n; ++i) cin >> qwq[i]; sort(qwq.begin(), qwq.end()); LL ans = 0; for (int i = 0; i < n - 1; ++i) { ans += (qwq[i + 1] - qwq[i]) * (LL)(i + 1) * (LL)(n - i - 1); } cout << ans << endl; } return 0; }
C. Covid (Hdu 6777)
题目大意
个人,告诉你每个人每刻的位置。如果有人和感染病毒的人在某一刻在同一位置,那么那人也被感染。初始只有1号人感染了,问最终感染人的编号。
解题思路
模拟时间流逝暴力搞就好了。
神奇的代码
#include <bits/stdc++.h> using namespace std; typedef long long LL; template <typename T> void read(T &x) { int s = 0, c = getchar(); x = 0; while (isspace(c)) c = getchar(); if (c == 45) s = 1, c = getchar(); while (isdigit(c)) x = (x << 3) + (x << 1) + (c ^ 48), c = getchar(); if (s) x = -x; } template <typename T> void write(T x, char c = ' ') { int b[40], l = 0; if (x < 0) putchar(45), x = -x; while (x > 0) b[l++] = x % 10, x /= 10; if (!l) putchar(48); while (l) putchar(b[--l] | 48); putchar(c); } int main(void) { int kase; read(kase); for (int ii = 1; ii <= kase; ii++) { int n; cin >> n; int tot = 0; vector<queue<pair<int, int>>> people(n); for (int len, t, p, i = 0; i < n; ++i) { cin >> len; for (int j = 1; j <= len; ++j) { cin >> t >> p; people[i].push(make_pair(t, p)); tot = max(t, tot); } } vector<bool> sign(n, 0); sign[0] = true; int pos[12] = {0}; for (int i = 1; i <= tot; ++i) { for (int j = 0; j < n; ++j) { if (sign[j] && (!people[j].empty()) && people[j].front().first == i) { pos[people[j].front().second] = i; } } for (int j = 0; j < n; ++j) { if ((!people[j].empty()) && people[j].front().first == i) { if (pos[people[j].front().second] == i) sign[j] = true; people[j].pop(); } } } printf("1"); for (int i = 2; i <= n; ++i) if (sign[i - 1]) printf(" %d", i); puts(""); } return 0; }
D. Car (Hdu 6778)
题目大意
周一到周五限制车尾号0-9,一周一个车位号只能限一次。告诉你车牌号,问如何限号,才能使得每天未被限制的车的数量的最小值最大。输出这个最值。
解题思路
枚举每个车位号应该在哪一天限制,爆搜就好了。也就种情况
神奇的代码
#include <bits/stdc++.h> using namespace std; typedef long long LL; template <typename T> void read(T &x) { int s = 0, c = getchar(); x = 0; while (isspace(c)) c = getchar(); if (c == 45) s = 1, c = getchar(); while (isdigit(c)) x = (x << 3) + (x << 1) + (c ^ 48), c = getchar(); if (s) x = -x; } template <typename T> void write(T x, char c = ' ') { int b[40], l = 0; if (x < 0) putchar(45), x = -x; while (x > 0) b[l++] = x % 10, x /= 10; if (!l) putchar(48); while (l) putchar(b[--l] | 48); putchar(c); } void DFS(int tot, int cnt[], int sum[], int &ans, int n) { if (tot == 10) { int qwq = 1e9; for (int i = 0; i < 5; ++i) { qwq = min(qwq, sum[i]); } ans = min(ans, n - qwq); return; } for (int i = 0; i < 5; ++i) { sum[i] += cnt[tot]; DFS(tot + 1, cnt, sum, ans, n); sum[i] -= cnt[tot]; } } int main(void) { int kase; read(kase); for (int ii = 1; ii <= kase; ii++) { int n; read(n); int cnt[10] = {0}; for (int x, i = 1; i <= n; ++i) { read(x); cnt[x % 10]++; } int ans = 1e9 + 7; int sum[5] = {0}; DFS(0, cnt, sum, ans, n); write(ans, '\n'); } return 0; }
E. Drink (Hdu 6779)
题目大意
有个人,告诉你他们对于可乐、雪碧、芬达的喜好程度的排序。现在你有可乐、雪碧、芬达瓶,问如何分配,使得他们的快乐值最大。若一个人喝到第一喜欢的,有3快乐值;第二喜欢的,有2快乐值;第三喜欢的,有1快乐值。
解题思路
就一道费用流裸题。
由于喜好程度的排序只有六种情况,把人数压成这六个点。
源点连三种饮料,容量为它们的瓶数,费用0。饮料连接六种情况,容量无穷,费用为相应的快乐值。六种情况连接汇点,容量为该情况的人数,费用为0。
由于是最大快乐值,把费用取相反数跑一遍最小费用最大流后取相反数即可。
神奇的代码
#include <bits/stdc++.h> using namespace std; typedef long long LL; template <typename T> void read(T &x) { int s = 0, c = getchar(); x = 0; while (isspace(c)) c = getchar(); if (c == 45) s = 1, c = getchar(); while (isdigit(c)) x = (x << 3) + (x << 1) + (c ^ 48), c = getchar(); if (s) x = -x; } template <typename T> void write(T x, char c = ' ') { int b[40], l = 0; if (x < 0) putchar(45), x = -x; while (x > 0) b[l++] = x % 10, x /= 10; if (!l) putchar(48); while (l) putchar(b[--l] | 48); putchar(c); } #define MIN(a, b) (((a) < (b) ? (a) : (b))) #define MAX(a, b) (((a) > (b) ? (a) : (b))) #define fo(i, a, b) for (int i = (a); i <= (b); ++i) #define M 30 #define N 12 const int INF = 23333333; int head[N], nxt[M * 2], to[M * 2], flow[M * 2], cost[M * 2], pre[N], dis[N], team[N * 5], val[N], fr[M * 2]; int num, u, v, w, st, en; bool vis[N]; LL ans; void add(int u, int v, int f, int w) { num++; nxt[num] = head[u]; to[num] = v; fr[num] = u; flow[num] = f; cost[num] = w; head[u] = num; num++; nxt[num] = head[v]; to[num] = u; fr[num] = v; flow[num] = 0; cost[num] = -w; head[v] = num; } inline bool SPFA() { int l = 0, r = 1; team[1] = st; fo(i, st, en) { dis[i] = INF; pre[i] = 0; vis[i] = false; } dis[st] = 0; vis[st] = 1; while (l < r) { u = team[++l]; for (int i = head[u]; i; i = nxt[i]) { v = to[i]; if (flow[i] && dis[v] > dis[u] + cost[i]) { dis[v] = dis[u] + cost[i]; pre[v] = i; if (!vis[v]) { team[++r] = v; vis[v] = 1; } } } vis[u] = 0; } if (pre[en]) return true; else return false; } inline void DFS() { int qwq = INF; for (int i = pre[en]; i; i = pre[fr[i]]) qwq = MIN(qwq, flow[i]); ans += (LL)qwq * (LL)dis[en]; for (int i = pre[en]; i; i = pre[fr[i]]) { flow[i] -= qwq; flow[i ^ 1] += qwq; } } int main(void) { int kase; read(kase); for (int ii = 1; ii <= kase; ii++) { num = 1; ans = 0; int n, a, b, c; read(n); read(a); read(b); read(c); st = 0; en = 10; char qwq[4]; int cnt[6] = {0}; for (int i = 1; i <= n; ++i) { scanf("%s", qwq); if (strcmp(qwq, "012") == 0) cnt[0]++; if (strcmp(qwq, "021") == 0) cnt[1]++; if (strcmp(qwq, "102") == 0) cnt[2]++; if (strcmp(qwq, "120") == 0) cnt[3]++; if (strcmp(qwq, "201") == 0) cnt[4]++; if (strcmp(qwq, "210") == 0) cnt[5]++; } add(st, 1, a, 0); add(st, 2, b, 0); add(st, 3, c, 0); add(1, 4, INF, -3); add(1, 5, INF, -3); add(1, 6, INF, -2); add(1, 7, INF, -1); add(1, 8, INF, -2); add(1, 9, INF, -1); add(2, 4, INF, -2); add(2, 5, INF, -1); add(2, 6, INF, -3); add(2, 7, INF, -3); add(2, 8, INF, -1); add(2, 9, INF, -2); add(3, 4, INF, -1); add(3, 5, INF, -2); add(3, 6, INF, -1); add(3, 7, INF, -2); add(3, 8, INF, -3); add(3, 9, INF, -3); add(4, en, cnt[0], 0); add(5, en, cnt[1], 0); add(6, en, cnt[2], 0); add(7, en, cnt[3], 0); add(8, en, cnt[4], 0); add(9, en, cnt[5], 0); while (SPFA()) DFS(); write(-ans, '\n'); for (int i = st; i <= en; ++i) head[i] = 0; } return 0; }
F. Cloth (Hdu 6780)
题目大意
晒衣服,U字型,告诉你竖着的长度和横着的长度的衣杆,衣服挂在上面,要求任意两件的距离不小于,问最大晒多少件。
解题思路
qwq
神奇的代码
qwq
G. Solo (Hdu 6781)
题目大意
有题,已知自己和对手完成每道题的时间,且对手从第1题开始写。问如何安排顺序,使得获得的分数最大。
每一道题第一个选手AC即得一分。若同时完成则我得一分。
我完成了可以选择任意时刻交,对手完成立刻交。
若有一题有人完成了,另一人会立刻放弃该题。
解题思路
一开始考虑的是设表示前题比对手超前分钟时获得的最大分数,由于分钟数达爆空间,所以考虑数据范围不那么大的状态。
设表示前题,得分为时的最大超前对手时间。
然后考虑能否完成第题以及是否写第题转移即可。
初始化,其余为。
答案就是中的最大值。
神奇的代码
#include <bits/stdc++.h> using namespace std; typedef long long LL; template <typename T> void read(T &x) { int s = 0, c = getchar(); x = 0; while (isspace(c)) c = getchar(); if (c == 45) s = 1, c = getchar(); while (isdigit(c)) x = (x << 3) + (x << 1) + (c ^ 48), c = getchar(); if (s) x = -x; } template <typename T> void write(T x, char c = ' ') { int b[40], l = 0; if (x < 0) putchar(45), x = -x; while (x > 0) b[l++] = x % 10, x /= 10; if (!l) putchar(48); while (l) putchar(b[--l] | 48); putchar(c); } const int N = 2e3 + 8; LL dp[N][N]; LL a[N], b[N]; int main(void) { int kase; read(kase); for (int ii = 1; ii <= kase; ii++) { int n; read(n); for (int i = 0; i <= n; ++i) for (int j = 0; j <= n; ++j) dp[i][j] = -1; for (int i = 1; i <= n; ++i) { read(a[i]); } for (int i = 1; i <= n; ++i) { read(b[i]); } dp[0][0] = 0; for (int i = 1; i <= n; ++i) for (int j = 0; j <= n; ++j) { if (dp[i - 1][j] != -1) { if (dp[i - 1][j] + b[i] >= a[i]) dp[i][j + 1] = max(dp[i][j + 1], dp[i - 1][j] - (a[i] - b[i])); dp[i][j] = max(dp[i][j], dp[i - 1][j] + b[i]); } } int ans = 0; for (int i = 0; i <= n; ++i) if (dp[n][i] != -1) ans = i; write(ans, '\n'); } return 0; }
H. Hanoi (Hdu 6782)
题目大意
qwq
解题思路
qwq
神奇的代码
qwq
本文作者:~Lanly~
本文链接:https://www.cnblogs.com/Lanly/p/13377585.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步