Replay
Dup4:
- 要是不挂机,再多仔细想想就好了
- J确实自闭好久,一直在想正确性,最后数据错了,喵喵喵?
- 还是要保证充足的休息啊,中间睡了一小会儿,也不知道睡了多久,醒来他们就又过了一道
- 要发掘题目更多的性质和有用条件啊,算法和数据结构只是工具,不要总想着这是啥题这是啥题,我会不会,其实我啥都不会
X:
- 日常挂机时间久,感觉是个不好的习惯。
- 太久没写了,已经不会算复杂度了, TLE MLE到自闭,转身写了个dp就过了?
- 感觉太容易根据数据想算法了, 自导自演。
- 自导自演,顺便演了16的C,演技拉满
扫描二维码关注公众号,回复:
5000125 查看本文章
A:机器人
Unsolved.
思路:
B:吃豆豆
Solved.
思路:
$dp[i][j][k]表示在(i, j)位置, 时间为t获得最多的糖果。$
$那么, 很显然有转移方程$
$dp[i][j][k] -> dp[i +1][j][k + 1]$
$dp[i][j][k] -> dp[i - 1][j][k + 1]$
$dp[i][j][k] -> dp[i][j + 1][k + 1]$
$dp[i][j][k] -> dp[i][j - 1][k + 1]$
$dp[i][j][k] -> dp[i][j][k + 1]$
$当时间k\%T[i][j] == 0时, dp[i][j][k]++$
$一共有n*m*c种状态, 复杂度是O(n*m*c)$
$然后我也不知道我为啥写了个滚动数组$
1 #include<bits/stdc++.h> 2 3 using namespace std; 4 5 const int maxn = 10 + 10; 6 7 int n, m, C; 8 int sx, sy, ex, ey; 9 int T[maxn][maxn]; 10 int arr[maxn][maxn]; 11 int brr[maxn][maxn]; 12 13 int main() 14 { 15 while(~scanf("%d %d %d", &n, &m, &C)) 16 { 17 for(int i = 1; i <= n; ++i) 18 { 19 for(int j = 1; j <= m; ++j) 20 { 21 scanf("%d", &T[i][j]); 22 } 23 } 24 scanf("%d %d %d %d", &sx, &sy, &ex, &ey); 25 memset(arr, -1, sizeof arr); 26 arr[sx][sy] = 0; 27 int step = 1; 28 for(step = 1; ; step++) 29 { 30 for(int i = 1; i <= n; ++i) 31 { 32 for(int j = 1; j <= m; ++j) 33 { 34 brr[i][j] = arr[i][j]; 35 } 36 } 37 for(int i = 1; i <= n; ++i) 38 { 39 for(int j = 1; j <= m; ++j) 40 { 41 if(i - 1 >= 1) arr[i][j] = max(arr[i][j], brr[i - 1][j]); 42 if(i + 1 <= n) arr[i][j] = max(arr[i][j], brr[i + 1][j]); 43 if(j - 1 >= 1) arr[i][j] = max(arr[i][j], brr[i][j - 1]); 44 if(j + 1 <= m) arr[i][j] = max(arr[i][j], brr[i][j + 1]); 45 if(step % T[i][j] == 0) 46 { 47 if(arr[i][j] >= 0) arr[i][j]++; 48 } 49 } 50 } 51 if(arr[ex][ey] >= C) break; 52 } 53 printf("%d\n", step); 54 } 55 return 0; 56 }
C:拆拆拆数
Solved.
思路:
1 #include<bits/stdc++.h> 2 3 using namespace std; 4 5 typedef long long ll; 6 7 ll GCD(ll a, ll b) 8 { 9 return b == 0 ? a : GCD(b, a % b); 10 } 11 12 ll a, b; 13 ll prime[] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53};//15 14 15 16 int main() 17 { 18 int t; 19 scanf("%d", &t); 20 while(t--) 21 { 22 scanf("%lld %lld", &a, &b); 23 if(GCD(a, b) == 1) 24 { 25 puts("1"); 26 printf("%lld %lld\n", a, b); 27 continue; 28 } 29 if(a == b) 30 { 31 if(a & 1) 32 { 33 ll ans1 = a / 2; 34 ll ans2 = a - a / 2; 35 puts("2"); 36 printf("%lld %lld\n", ans1, ans2); 37 printf("%lld %lld\n", ans2, ans1); 38 } 39 else 40 { 41 ll ans1 = a / 2 - 1; 42 ll ans2 = a - ans1; 43 puts("2"); 44 printf("%lld %lld\n", ans1, ans2); 45 printf("%lld %lld\n", ans2, ans1); 46 } 47 continue; 48 } 49 if(a % 2 == 1 && b % 2 == 1) 50 { 51 ll ans1 = 2, ans2 = a - 2; 52 ll ans3 = b - 2, ans4 = 2; 53 puts("2\n"); 54 printf("%lld %lld\n", ans1, ans3); 55 printf("%lld %lld\n", ans2, ans4); 56 } 57 else 58 { 59 int isswap = 0; 60 if(b % 2 == 0) 61 { 62 swap(a, b); 63 isswap = 1; 64 } 65 int flag = 0; 66 ll ans1, ans2, ans3, ans4; 67 ans3 = b - 2; 68 ans4 = 2; 69 for(int i = 1; i <= 15 && prime[i] + 2 <= a; ++i) 70 { 71 if((b - 2) % prime[i] != 0) 72 { 73 flag = 1; 74 ans1 = prime[i]; 75 ans2 = a - prime[i]; 76 break; 77 } 78 } 79 if(flag) 80 { 81 if(isswap) 82 { 83 swap(ans1, ans3); 84 swap(ans2, ans4); 85 } 86 puts("2"); 87 printf("%lld %lld\n", ans1, ans3); 88 printf("%lld %lld\n", ans2, ans4); 89 continue; 90 } 91 ans3 = b - b % a - 1; 92 ans4 = b - ans3; 93 for(int i = 0; i <= 15 && prime[i] + 2<= a; ++i) 94 { 95 ans1 = prime[i]; 96 ans2 = a - prime[i]; 97 if(GCD(ans1, ans3) == 1 && GCD(ans2, ans4) == 1) 98 { 99 flag = 1; 100 break; 101 } 102 } 103 if(flag) 104 { 105 if(isswap) 106 { 107 swap(ans1, ans3); 108 swap(ans2, ans4); 109 } 110 puts("2"); 111 printf("%lld %lld\n", ans1, ans3); 112 printf("%lld %lld\n", ans2, ans4); 113 } 114 else 115 { 116 puts("-1"); 117 } 118 } 119 } 120 return 0; 121 }
F:爬爬爬山
Solved.
思路:
考虑海拔和体力的关系,即最高可以爬的山为$h[1] + k$
那么对于其他高度不符合的山,我们就需要降低其高度
可以理解为点有点权,边有边权,经过边和点都要加上其权值,求最短路
将一个点拆成两个点,中间连条有向边,权值为该点点权,再跑最短路即可
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 #define ll long long 5 #define N 200010 6 #define INFLL 0x3f3f3f3f3f3f3f3f 7 int n, m, k, h[N]; 8 ll d; 9 struct Graph 10 { 11 struct node 12 { 13 int to, nx; ll w; 14 node () {} 15 node (int to, int nx, ll w) : to(to), nx(nx), w(w) {} 16 }a[N << 3]; 17 int head[N], pos; 18 void init() 19 { 20 memset(head, 0, sizeof head); 21 pos = 0; 22 } 23 void add(int u, int v, ll w) 24 { 25 a[++pos] = node(v, head[u], w); head[u] = pos; 26 } 27 }G; 28 #define erp(u) for (int it = G.head[u], v = G.a[it].to; it; it = G.a[it].nx, v = G.a[it].to) 29 30 struct node 31 { 32 int to; ll w; 33 node () {} 34 node (int to, ll w) : to(to), w(w) {} 35 bool operator < (const node &other) const { return w > other.w; } 36 }; 37 ll dist[N]; bool used[N]; 38 void Dijkstra() 39 { 40 for (int i = 1; i <= 2 * n + 1; ++i) dist[i] = INFLL, used[i] = false; 41 dist[2] = 0; priority_queue <node> pq; pq.push(node(2, 0)); 42 while (!pq.empty()) 43 { 44 int u = pq.top().to; pq.pop(); 45 if (used[u]) continue; 46 used[u] = true; 47 erp(u) 48 { 49 ll w = G.a[it].w; 50 if (!used[v] && dist[v] > dist[u] + w) 51 { 52 dist[v] = dist[u] + w; 53 pq.push(node(v, dist[v])); 54 } 55 } 56 } 57 } 58 59 int main() 60 { 61 while (scanf("%d%d%d", &n, &m, &k) != EOF) 62 { 63 G.init(); 64 for (int i = 1; i <= n; ++i) scanf("%d", h + i); 65 d = h[1] + k; 66 for (int i = 1, u, v, w; i <= m; ++i) 67 { 68 scanf("%d%d%d", &u, &v, &w); 69 G.add(2 * u + 1, 2 * v, w); 70 G.add(2 * v + 1, 2 * u, w); 71 } 72 for (int i = 1; i <= n; ++i) 73 { 74 ll w = 0; 75 if (h[i] > d) w = 1ll * (h[i] - d) * (h[i] - d); 76 G.add(2 * i, 2 * i + 1, w); 77 } 78 Dijkstra(); 79 printf("%lld\n", dist[2 * n + 1]); 80 } 81 return 0; 82 }
J:夺包奇兵
思路:
考虑居民拥有的最大宝物数为$m$
可以枚举这个值,贪心$check()$即可
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 #define ll long long 5 #define N 1010 6 int n, m; 7 vector <int> v[N]; 8 9 ll check(int x) 10 { 11 ll res = 0; 12 int cnt = 0; 13 priority_queue <int, vector <int>, greater <int> > q; 14 for (int i = 1; i <= n; ++i) 15 { 16 int need = v[i].size() - x; 17 for (auto it : v[i]) 18 { 19 if (need > 0) 20 { 21 --need; 22 res += it; 23 ++cnt; 24 } 25 else 26 q.push(it); 27 } 28 } 29 while (cnt <= x) 30 { 31 ++cnt; 32 res += q.top(); q.pop(); 33 } 34 return res; 35 } 36 37 int main() 38 { 39 while (scanf("%d%d", &n, &m) != EOF) 40 { 41 for (int i = 1; i <= n; ++i) v[i].clear(); 42 for (int i = 1, a, c; i <= m; ++i) 43 { 44 scanf("%d%d", &a, &c); 45 v[c].push_back(a); 46 } 47 for (int i = 1; i <= n; ++i) sort(v[i].begin(), v[i].end()); 48 ll res = (ll)1e18; 49 for (int i = 0; i < m; ++i) 50 res = min(res, check(i)); 51 printf("%lld\n", res); 52 } 53 return 0; 54 }