首页 > 其他分享 >GDCPC2023 B , D , F , K 题解

GDCPC2023 B , D , F , K 题解

时间:2023-10-03 19:55:18浏览次数:34  
标签:node const int 题解 棋子 邻居 GDCPC2023

和队友一起打的 2023 年广东省大学生程序设计竞赛重现赛,写了 B, D, K,胡了一个 F。

D

题目大意

随着广东的建设与发展,越来越多人选择来到广东开始新生活。在一片新建的小区,有 \(n\) 个人要搬进 \(m\) 栋排成一行的房子,房子的编号从 \(1\) 到 \(m\)(含两端)。房子 \(u\) 和 \(v\) 相邻,当且仅当 \(|u-v|=1\)。我们需要为每一个人安排一栋房子,要求所有人入住的房子互不相同。若两个人住进了一对相邻的房子,则这两个人互为邻居。

有的人喜欢自己有邻居,而有的人不喜欢。对于第 \(i\) 个人,如果他有至少一位邻居,则他的满意度为 \(a_i\);否则如果他没有邻居,则他的满意度为 \(b_i\)。

您作为小区的规划者,需要最大化所有人的总满意度。

题解。

可以发现最优解一定是:

AAA.B.B.B

或者:

B.B.B.B.B.B

或:

AAAAAA

其中 AB 分别表示有邻居的人和没有邻居的人。

让我们贪心地想,这里面的 A 一定是那些 \(b_i - a_i\) 最小的人,因为如果将 \(b_i - a_i\) 较大的人排为 A,把他放到 B 中对答案的贡献显然更大。

所以按照 \(b_i - a_i\) 从小到大排序,再枚举 \(i\) ( \(2\leqslant i\leqslant n - 1\) ),把 \(1 \sim i\) 当成有邻居的,\(i + 1 \sim n\) 当作没有邻居的,对这些情况取 \(\max\) 即可。

最后还要特判全是 A 和全是 B 的情况。

code:

#include <bits/stdc++.h>

using namespace std;

const int N = 5e5 + 5;
int n, m;
struct node {
  int a, b;
  inline bool operator < (const node &w) const {
    return (b - a) < (w.b - w.a);
  }
} a[N];

void solve() {
  cin >> n >> m;
  for (int i = 1; i <= n; ++i) cin >> a[i].a >> a[i].b;
  sort(a + 1, a + 1 + n);
  vector <long long> pre(n + 1, 0), suf(n + 2, 0);
  for (int i = 1; i <= n; ++i) pre[i] = pre[i - 1] + a[i].a;
  for (int i = n; i; --i) suf[i] = suf[i + 1] + a[i].b;
  long long ans = 0;
  for (int i = 0; i <= n; ++i) {
    if (i == 1) continue;
    int need = i + (n - i) * 2 - (!i);
    if (need <= m) ans = max(ans, pre[i] + suf[i + 1]);
  } cout << ans << '\n';
}

signed main(void) {
  ios :: sync_with_stdio(false);
  cin.tie(nullptr); cout.tie(nullptr);
  int T; cin >> T; while (T--) solve();
}

K

题目大意

独立钻石是一种单人桌游。游戏在 \(n\) 行 \(m\) 列的棋盘上进行,棋盘上的每一格要么是空格,要么有一枚棋子。一开始,棋盘上共有 \(k\) 枚棋子。

在游戏中,玩家可以选择一枚棋子,将它跳过相邻棋子到空格上,并移除被跳过的棋子。具体来说,令 \((i, j)\) 表示位于第 \(i\) 行第 \(j\) 列的格子,玩家可以执行以下四种操作。

给定一个初始的棋盘,求经过任意次操作(包括零次)之后,棋盘上最少能剩余几枚棋子。

题解

由于 \(n, m, k\leqslant 6\),可以不用剪枝,直接搜索。

细节具体请看代码实现。

code:

#include <bits/stdc++.h>

using namespace std;

const int N = 7;

int n, m, k;
int a[N][N]; //a[i][j] 表示 (i, j) 的信息,如果为 0 表示这个格子为空,否则表示这个格子上有哪个棋子。
bool vis[N]; //vis[i] 表示第 i 个棋子是否被选过。

struct node {
  int x, y;
  node (int xx, int yy) {x = xx, y = yy;}
} ; //记录棋子坐标
vector <node> v;

int dx[4] = {0, 0, -1, 1}, dy[4] = {1, -1, 0, 0};
int ans = 0;

void dfs(int cnt) {
  ans = min(ans, cnt);
  for (int i = 0; i < k; ++i) if (!vis[i]) {
    for (int j = 0; j < 4; ++j) {
      int nx = v[i].x + dx[j], ny = v[i].y + dy[j];
      if (nx && ny && nx <= n && ny <= m && a[nx][ny] != 0) { 
        int tx = nx + dx[j], ty = ny + dy[j];
        if (tx && ty && tx <= n && ty <= m && a[tx][ty] == 0) {
          a[tx][ty] = i + 1; a[v[i].x][v[i].y] = 0;
          vis[a[nx][ny] - 1] = 1; 
          int nt = a[nx][ny]; a[nx][ny] = 0; 
          swap(v[i].x, tx); swap(v[i].y, ty); 
          dfs(cnt - 1);
          swap(v[i].x, tx); swap(v[i].y, ty);
          a[tx][ty] = 0; a[v[i].x][v[i].y] = i + 1;
          a[nx][ny] = nt; vis[i] = vis[a[nx][ny] - 1] = 0; //记得还原信息。
        }
      }
    }
  }
}

signed main(void) {
  ios :: sync_with_stdio(false);
  cin.tie(nullptr); cout.tie(nullptr);
  int T; cin >> T; while (T--) {
    cin >> n >> m >> k; ans = k;
    for (int i = 1; i <= n; ++i) for (int j = 1; j <= m; ++j)
      a[i][j] = 0; //多测要清空
    v.clear(); for (int i = 1; i <= k; ++i) {
      int x, y; cin >> x >> y;
      v.emplace_back(node(x, y));
      a[x][y] = i; vis[i - 1] = 0;
    } dfs(k); cout << ans << '\n';
  }
}

标签:node,const,int,题解,棋子,邻居,GDCPC2023
From: https://www.cnblogs.com/CTHOOH/p/17741570.html

相关文章

  • 题解 [CSP-S 2021] 括号序列
    题目链接对于括号题,基本是栈匹配没有匹配的左括号和区间\(dp\)两个方向。这道题括号序列并不确定,只能用区间\(dp\)搞。如果直接设\(f_{l,r}\)表示\(l\simr\)的合法括号序列,那么由区间\(dp\)的套路可知,需要枚举中间点进行合并,那么\(()()()\)的情况就会出问题,原因是......
  • 【UVA 12100】Printer Queue 题解(队列+优先队列)
    计算机科学学生会中唯一的打印机正经历着极其繁重的工作量。有时,打印机队列中有100个作业,您可能需要等待数小时才能获得一页输出。由于某些作业比其他作业更重要,黑客将军为打印作业队列发明并实现了一个简单的优先级系统。现在,为每个作业分配1到9之间的优先级(9是最高优先级,1是最低......
  • [题解]CF1748C Zero-Sum Prefixes
    UPD23.10.3更新的对思路的描述,以及代码。思路对于每一个\(a_i=0\),如果我们将它变为\(x\),都可以直接将\(i\simn\)位置上的前缀和加\(x\)。设\(a_j\)是\(a_i\)后第一个\(0\),那么,在\(j\)时同样有上述规律。所以,我们只需在\(i\)时考虑,\(i\sim(j-1)\)的贡......
  • 题解 [蓝桥杯 2016 省 B] 交换瓶子
    题目链接本题解讲解环图的做法。要将一个\(1\simn\)的排列通过交换变成\(1\simn\),可以先将\(i\)向\(a_i\)连边,那么最终一定会练成若干个环(每个点只有一个出度,也只有一个入度)。假设交换在同一个环中的节点,一个环显然会变成两个环,也就是说,交换一次最多增加一个环的数量,......
  • 【题解】洛谷 P1003 [NOIP2011 提高组] 铺地毯
    原题链接解题思路如果直接按照题意开一个二维数组来模拟每个点最上面的地毯编号,会发现所占空间最坏情况下约为(2*105)2*4B=4*1010*4B=1.6*1011B≈149GB,程序完全无法运行。但实际上没有必要将每一个点的信息记录下来,只需要记录每一块地毯能覆盖哪些点,再依次判断哪那些地毯可以......
  • 「题解」Codeforces Round 894 (Div. 3)
    A.GiftCarpetProblem题目Sol&Code签到题#include<bits/stdc++.h>#defineN21typedeflonglongll;intmin(inta,intb){returna<b?a:b;}intmax(inta,intb){returna>b?a:b;}intT,n,m,a[4];std::strings[N];i......
  • T2回家(home)题解
    T2回家(home)现在啥也不是了,虽然会了逆元,但是对期望概率题还是一窍不通,赛时相当于只推出了\(n=1\)的情况,结果运用到所有情况,理所应当只有20分。题目描述小Z是个路痴。有一天小Z迷路了,此时小Z到家有NN个单位长度。小Z可以进行若干次行动,每次行动小Z有\(\frac12\)的概率向......
  • [ARC035B] アットコーダー王国のコンテスト事情 题解
    前置芝士排列组合分析明显的贪心,第一问与此题思路相似,优先选择做时间少的,可以尽可能让后面的罚时尽量的小。难点在第二问,第二问问的是有几种可能性,有个显然的结论:相同做题时间的题目,位置调换答案仍然相同。那么可以用桶+排列组合来解决:用桶储存这个做题时间的出现次数\(b......
  • AT_abc321_f 题解
    #思路简单动态规划,$dp_i$指当前操作后取和为$i$的球的方案数,每次输出$dp_K$即可。需要注意的是对于每次`+x`操作,计算$dp$数组时要倒着循环。时间复杂度:$O(QK)$。#代码```cpp#include<bits/stdc++.h>usingnamespacestd;longlongdp[5010];intmain(){ longlon......
  • RDP远程登录后全屏,本地的任务栏始终显示的问题解决
    文章目录问题解决参考问题RDP远程登录后全屏,本地的任务栏(TaskBar)始终在下面,遮住了远程桌面的最下面,进行了解决。解决BestsolutionhowtohidelocalTaskbarwhenRDPtoaremotedesktopLaunchTaskManagerRight-click“WindowsExplorer”Select“Restart”Itworkson......