D. Deja vu of … Go Players
签。
1 #include <bits/stdc++.h> 2 using namespace std; 3 int t, n, m; 4 5 int main() 6 { 7 scanf("%d", &t); 8 while (t--) 9 { 10 scanf("%d%d", &n, &m); 11 for (int i = 1; i <= n + m; ++i) scanf("%*d"); 12 puts(n <= m ? "Yes" : "No"); 13 } 14 return 0; 15 }
I. Misunderstood … Missing
题意:
$有n轮游戏,每一轮有三个参数a_i, b_i, c_i$
初始攻击力为$A = 0, 成长值为D = 0$
每一轮的开头 $A = A + D$
接着三种操作选一个
- 造成$A + a_i点伤害$
- $D = D + b_i$
- $A = A + c_i$
求造成的最大伤害和是多少
思路:
倒着$dp, dp[i][j][k] 表示当前处于第i轮,在后面的轮数中要进行j次攻击,时间点之和为k$
那么到当前点,我们就可以
通过$k;来算出如果当前点选择第二种操作的贡献$
$dp[i][j][k] = max(dp[i][j][k], dp[i + 1][j][k] + c[i] * j)$
$通过j;来算出如果当前点选择第三种操作的贡献$
$dp[i][j][k] = max(dp[i][j][k], dp[i + 1][j][k] + (k - i * j) * b[i])$
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 #define ll long long 5 #define N 110 6 #define M 6010 7 int t, n; 8 ll dp[2][N][M], a[N], b[N], c[N]; 9 10 int main() 11 { 12 scanf("%d", &t); 13 while (t--) 14 { 15 scanf("%d", &n); 16 for (int i = 1; i <= n; ++i) scanf("%lld%lld%lld", a + i, b + i, c + i); 17 for (int i = 0; i < 2; ++i) for (int j = 0; j <= n; ++j) for (int k = 0; k <= 5050; ++k) dp[i][j][k] = -1; 18 dp[n & 1 ^ 1][0][0] = 0; 19 for (int i = n; i >= 1; --i) 20 { 21 for (int j = 0; j <= n; ++j) for (int k = 0; k <= 5050; ++k) if (dp[i & 1 ^ 1][j][k] != -1) 22 { 23 dp[i & 1][j + 1][k + i] = max(dp[i & 1][j + 1][k + i], dp[i & 1 ^ 1][j][k] + a[i]); 24 dp[i & 1][j][k] = max(dp[i & 1][j][k], dp[i & 1 ^ 1][j][k] + 1ll * j * c[i]); 25 dp[i & 1][j][k] = max(dp[i & 1][j][k], dp[i & 1 ^ 1][j][k] + 1ll * (k - j * i) * b[i]); 26 } 27 } 28 ll res = 0; 29 for (int i = 1; i <= n; ++i) for (int j = 1; j <= 5050; ++j) res = max(res, dp[1][i][j]); 30 printf("%lld ", res); 31 } 32 return 0; 33 }
L. Eventual … Journey
题意:
有两个阵营,阵营之间的人可以两两之间通过花费1来相互到达
不同阵营之间如果有直接边也可以直接相互到达,如果没有直接边,可以通过间接到达
即先到达一个有边连到对方阵营的同阵营的人,再过去
思路:
考虑花费一共有三种情况
1:同阵营之间的相互到达,不同阵营之间有边可以直接到达
2:不同阵营之间没有直接边,但是有一方有直接边连向对方阵营
3:两个属于不同阵营,且都没有直接边连向对方阵营
要注意m = 0的时候,不同阵营之间不可达
还有 它给出的公共边可能有相同阵营的
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 #define N 100010 5 int n, m; 6 int cnt[2], zero[2], degree[N], vis[N]; 7 8 int main() 9 { 10 while (scanf("%d%d", &n, &m) != EOF) 11 { 12 memset(degree, 0, sizeof degree); 13 cnt[0] = cnt[1] = 0; 14 zero[0] = zero[1] = 0; 15 for (int i = 1; i <= n; ++i) 16 { 17 scanf("%d", vis + i); 18 ++cnt[vis[i]]; 19 } 20 if (m == 0) 21 { 22 for (int i = 1; i <= n; ++i) printf("%d%c", cnt[vis[i]] - 1, " "[i == n]); 23 continue; 24 } 25 for (int i = 1, u, v; i <= m; ++i) 26 { 27 scanf("%d%d", &u, &v); 28 if (vis[u] == vis[v]) continue; 29 ++degree[u]; 30 ++degree[v]; 31 } 32 for (int i = 1; i <= n; ++i) if (!degree[i]) 33 ++zero[vis[i]]; 34 for (int i = 1; i <= n; ++i) 35 { 36 int res = 0; 37 if (degree[i]) res = cnt[vis[i]] - 1 + degree[i] + (cnt[vis[i] ^ 1] - degree[i]) * 2; 38 else res = cnt[vis[i]] - 1 + cnt[vis[i] ^ 1] * 2 + zero[vis[i] ^ 1]; 39 printf("%d%c", res, " "[i == n]); 40 } 41 } 42 return 0; 43 }