CCPC-Wannafly Winter Camp Day1 (Div2, onsite)

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 }
View Code

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 }
View Code

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 }
View Code

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 }
View Code

猜你喜欢

转载自www.cnblogs.com/Dup4/p/10296448.html