赞
踩
题目来源及知识点
A:(贪心)
B:《算法竞赛进阶指南》-0x54.例题.没有上司的舞会(树形DP)
C:USACO 2015 January Contest Bronze-A.Cow Routing(模拟)
D:LeetCode.2327-知道秘密人数(前缀和、DP)
E:CodeForce Round #806(Div.4)-B.ICPC Balloons(模拟)
(由于C、E两题较简单所以就没有写解析,代码必要地方有注释)
Problem.A 打包烧饼
本题使用的就是贪心,先用减去
,得到每个餐盒里还需要的烧饼的数量,然后将其从小到大排序,优先往需求小的餐盒里放,这样能保证最后能被放满的餐盒数量最多。
- #pragma GCC optimize(2)
- #include <bits/stdc++.h>
- using namespace std;
- #define endl '\n'
- #define int long long
-
- const int N = 50010;
- int n, m, r, c[N];
-
- void solve()
- {
- cin >> n >> m;
- for (int i = 1; i <= n; i++)
- {
- cin >> c[i];
- }
- for (int i = 1; i <= n; i++)
- {
- cin >> r;
- c[i] -= r;
- }
- sort(c + 1, c + 1 + n);
- int ans = 0;
- for (int i = 1; i <= n; i++)
- {
- if (m < c[i])
- break;
- ans++;
- m -= c[i];
- }
- cout << ans << endl;
- }
-
- signed main()
- {
- ios::sync_with_stdio(false);
- cin.tie(0); cout.tie(0);
- solve();
- return 0;
- }

Problem.B 开黑之夜
本题很容易知道这个关系结构是个树形结构,每个人的happy值都作为节点的权值。要求解的是最优子结构,那么这就是个树形DP的问题。
令表示在以i为子树的员工中选择一些人参加活动且不包括i时的总happy值,
表示以i为子树的员工中选择一些人参加活动且包括i时的happy值。
当第i个人不参加活动时,它的直接下属(子节点)可以参加,也可以不参加,即状态转移方程为
(表示i的子节点的集合,下同)
当第i个人参加活动时,它的直接下属(字节点)一定不参加活动,即状态转移方程为
( 表示第i个人的happy值)
则我们需要找到的是以老板作为根节点时的最大值,假设老板节点为boss,即要求解,那么本题就可以以DFS的方式来求出每个子树的最大happy值依次向上传递。
- #pragma GCC optimize(2)
- #include <bits/stdc++.h>
- using namespace std;
- #define endl '\n'
- #define int long long
-
- const int N = 6010, M = 12010;
- int n, a[N]; //a[]:happy值
- int h[N], e[M], ne[M], idx; //邻接表存储树
- int dp[N][2];
- bool st[N]; //该节点是否有父节点
-
- void init()
- {
- memset(h, -1, sizeof(h));
- idx = 0;
- }
-
- //连接一条从p到s的边,p是s的直接上级
- void add(int p, int s)
- {
- e[idx] = s;
- ne[idx] = h[p];
- h[p] = idx++;
- }
-
- void dfs(int u)
- {
- dp[u][1] = a[u];
- for (int i = h[u]; i != -1; i = ne[i])
- {
- int j = e[i];
- dfs(j);
- dp[u][0] += max(dp[j][0], dp[j][1]);
- dp[u][1] += dp[j][0];
- }
- }
-
- void solve()
- {
- init();
- cin >> n;
- for (int i = 1; i <= n; i++)
- {
- cin >> a[i];
- }
- int s, p;
- for (int i = 1; i < n; i++)
- {
- cin >> s >> p;
- add(p, s);
- st[s] = true;
- }
- int boss= 1;
- //没有父节点的点就是老板
- while (st[boss])
- {
- boss++;
- }
- dfs(boss);
- cout << max(dp[boss][0], dp[boss][1]) << endl;
- }
-
- signed main()
- {
- ios::sync_with_stdio(false);
- cin.tie(0); cout.tie(0);
- solve();
- return 0;
- }

Problem.C 旅游线路
- #pragma GCC optimize(2)
- #include <bits/stdc++.h>
- using namespace std;
- #define endl '\n'
- #define int long long
-
- int a, b, n;
-
- void solve()
- {
- cin >> a >> b >> n;
- int ans = 1010;
- while (n--)
- {
- int sum, m, pos;
- cin >> sum >> m;
- bool flag = false;
- while (m--)
- {
- cin >> pos;
- if (pos == a) //找到了出发起点
- flag = true;
- if (pos == b && flag) //找到了终点
- ans = min(ans , sum);
- }
- }
- if (ans == 1010)
- cout << -1 << endl;
- else
- cout << ans <<endl;
- }
-
- signed main()
- {
- ios::sync_with_stdio(false);
- cin.tie(0); cout.tie(0);
- solve();
- return 0;
- }

Problem.D 十七的秘密
本题也是采用动态规划,表示第i天新增知道秘密的人数,初始时
,其余为0。对于
,新增的人数为区间
内知道秘密的人数之和,那么最终答案就是区间
内知道秘密的人数之和。
根据以上分析实际上我们可以采用前缀和来求区间和,因此表示第1天到第i天新增的知道秘密的人的前缀和,则状态转移方程为
那么最终第n天知道还秘密的人数就是,要注意的是
和
不能为负。
- #pragma GCC optimize(2)
- #include <bits/stdc++.h>
- using namespace std;
- #define endl '\n'
- #define int long long
-
- const int N = 1010, mod = 1e9 + 7;
- int n, d1, d2, dp[N];
-
- void solve()
- {
- cin >> n >> d1 >> d2;
- dp[0] = 0, dp[1] = 1;
- for (int i = 2; i <= n; i++)
- {
- dp[i] = dp[i - 1];
- if (i >= d1)
- dp[i] = (dp[i] + dp[i - d1]) % mod;
- if (i >= d2)
- dp[i] = (dp[i] - dp[i - d2]) % mod;
- }
- cout << ((dp[n] - dp[n - d2]) % mod + mod) % mod << endl;
- }
-
- signed main()
- {
- ios::sync_with_stdio(false);
- cin.tie(0); cout.tie(0);
- solve();
- return 0;
- }

Problem.E ICPC的气球
- #pragma GCC optimize(2)
- #include <bits/stdc++.h>
- using namespace std;
- #define endl '\n'
- #define int long long
-
- map<char,int> ball;
- int t, n;
- string s;
-
- void solve()
- {
- cin >> s;
- int ans = 0;
- for (auto c: s)
- {
- if (ball[c] == 0) //如果该字母第一次出现
- ans+=2; //加两个气球
- else
- ans++;
-
- ball[c]++; //存入map
- }
- cout << ans << endl;
- ball.clear(); //处理完一组数据清空map
- }
-
- signed main()
- {
- ios::sync_with_stdio(false);
- cin.tie(0); cout.tie(0);
- cin >> t;
- while (t--)
- {
- solve();
- }
- return 0;
- }

Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。