Yahoo Programming Contest 2019

A - Anti-Adjacency

签.

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 int main()
 5 {
 6     int n, k;
 7     while (scanf("%d%d", &n, &k) != EOF)
 8     {
 9         int remind = (n + 1) / 2;
10         puts(k <= remind ? "YES" : "NO");
11     }
12     return 0;
13 }
View Code

B - Path

签.

#include <bits/stdc++.h>
using namespace std;

int x, y, Max;
vector <int> G[5];

void DFS(int u, int fa, int deep)
{
    Max = max(Max, deep);
    for (auto v : G[u]) if (v != fa)
        DFS(v, u, deep + 1);
}

int main()
{
    while (scanf("%d%d", &x, &y) != EOF)
    {
        for (int i = 1; i <= 4; ++i) G[i].clear();
        G[x].push_back(y);
        G[y].push_back(x);
        for (int i = 1; i <= 2; ++i)
        {
            scanf("%d%d", &x, &y);
            G[x].push_back(y);
            G[y].push_back(x);
        }
        Max = 0;
        DFS(1, 1, 1);
        puts(Max == 4 ? "YES" : "NO");
    }
    return 0;
}
View Code

C - When I hit my pocket...

签.

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 #define ll long long
 5 int k, a, b;
 6 
 7 int main()
 8 {
 9     while (scanf("%d%d%d", &k, &a, &b) != EOF)
10     {
11         if (a >= (b - 2) || k < a) printf("%d
", k + 1);
12         else
13         {
14             k -= a - 1;
15             int Loop = k / 2;
16             if (Loop == 0) printf("%d
", a + k % 2);
17             else printf("%lld
", 1ll * b + 1ll * (Loop - 1) * (b - a) + k % 2);
18         }
19     }
20     return 0;
21 }
View Code

D - Ears

Upsolved.

题意:

有一个人在一维线段上走

$每次经过i - 0.5  i 是整数, 就在第i个位置放一颗石头$

$并且起点和终点必须是整数点,只能在整数点向$

$这样一条合法的路径可以用一个石头序列来表示$

$现在给出每个位置的石头数量,这个可能是不合法的$

$但是可以在某个位置放置或者移除一块石头$

$求最少的操作次数使得石头序列合法$

思路:

我们考虑一个合法的石头序列肯定是

零碎 + 偶数 + 奇数 + 偶数 + 零碎

这样五部分构成,并且至少有一部分的个数不为$0$

我们考虑$dp[i][j] 表示第i个位置,当前点位于第j个状态$

$转移即可$

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 #define ll long long
 5 #define N 200010
 6 int n, a[N];
 7 ll f[N][5];
 8 
 9 int main()
10 {
11     while (scanf("%d", &n) != EOF)
12     {
13         for (int i = 1; i <= n; ++i) scanf("%d", a + i);
14         memset(f, 0x3f, sizeof f);
15         for (int i = 0; i < 5; ++i) f[0][i] = 0;
16         // 0 左边零碎
17         // 1 左边偶数
18         // 2 奇数
19         // 3 右边偶数
20         // 4 右边零碎
21         for (int i = 1; i <= n; ++i)
22         {
23             ll Min = (ll)1e18, cost;
24             cost = a[i];
25             Min = min(Min, f[i - 1][0]);
26             f[i][0] = Min + cost;
27             
28             cost = a[i] == 0 ? 2 : (a[i] % 2);
29             Min = min(Min, f[i - 1][1]);
30             f[i][1] = Min + cost;
31 
32             cost = a[i] == 0 ? 1 : (a[i] % 2 == 0);
33             Min = min(Min, f[i - 1][2]);
34             f[i][2] = Min + cost;
35             
36             cost = a[i] == 0 ? 2 : (a[i] % 2);
37             Min = min(Min, f[i - 1][3]);
38             f[i][3] = Min + cost;
39 
40             cost = a[i];
41             Min = min(Min, f[i - 1][4]);
42             f[i][4] = Min + cost;
43         }
44         ll res = (ll)1e18;
45         for (int i = 0; i < 5; ++i)
46             res = min(res, f[n][i]);
47         printf("%lld
", res);
48     }
49     return 0;
50 }
View Code

F - Pass

Upsolved.

题意:

$有n个人,每个人手中有两个球,球有红蓝两种$

$0代表手中有两个红球$

$1代表手中有一红一蓝$

$2代表手中有两个蓝球$

$每次每个编号为非1的人,如果手中还有球,那就挑一个球给前面的人$

$编号为1的人,如果手中有球,就将球接到结果集中$

$最后结果集为一个长度为2 cdot n的字符串,r 代表红球, b代表蓝球$

$求结果集的方案数$

思路:

$dp[i][j] 表示到第i位,已经安排了j个红球的方案数$

$那只需要考虑i + 1这一位能不能放红球后者能不能放蓝球,就能确定转移$

$我们考虑第i个人的球至少要放在第i位或者之后$

$因为传递需要一个过程$

$用前缀和维护一下,就可以知道前i位最多放多少红球, 转移即可$

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 #define ll long long
 5 #define N 4010
 6 const ll MOD = (ll)998244353;
 7 int n;
 8 char s[N];
 9 ll f[N][N];
10 int a[N], b[N];
11 
12 template <class T>
13 void add(T &x, T &y) { x += y; if (x >= MOD) x -= MOD; }
14 
15 int main()
16 {
17     while (scanf("%s", s + 1) != EOF)
18     {
19         n = strlen(s + 1);
20         for (int i = 1; i <= n; ++i) a[i] = a[i - 1] + 2 - (s[i] - '0'), b[i] = b[i - 1] + s[i] - '0';
21         memset(f, 0, sizeof f);
22         f[0][0] = 1;
23         for (int i = 0; i <= 2 * n; ++i)
24             for (int j = 0; j <= i; ++j) if (f[i][j])
25             {
26                 if (a[min(i + 1, n)] > j) add(f[i + 1][j + 1], f[i][j]);
27                 if (b[min(i + 1, n)] > i - j) add(f[i + 1][j], f[i][j]);
28             }
29         printf("%lld
", f[2 * n][a[n]]);
30     }
31     return 0;
32 }
View Code
原文地址:https://www.cnblogs.com/Dup4/p/10358313.html