• 特此声明:该文章中的代码和解法均来自博主cup-pyy,我只是对其代码添加了详细注解,以及部分思路的详细化,原文链接见:这里

二维平面转为一维

注意我们最多含有22个坐标,但是实际上只会有21*21个格子
如何判断二维平面中的格子数量全部染黑?一维情况状态压缩十分容易,二维的情况将若干个一维拼接即可

        bitset<500> t;//二维平面转换为一维//虽然22个坐标// 21 * 21个格子看看是否都能染满lop(i, 0, n){r[i].a.x = lower_bound(xs + 1, xs + cntx + 1, r[i].a.x) - xs;r[i].a.y = lower_bound(ys + 1, ys + cnty + 1, r[i].a.y) - ys;r[i].b.x = lower_bound(xs + 1, xs + cntx + 1, r[i].b.x) - xs;r[i].b.y = lower_bound(ys + 1, ys + cnty + 1, r[i].b.y) - ys;mask[i].reset();//t.reset();//标记一个格子被染黑,表示这个格子的左下角被染黑t = (1 << (r[i].b.y - r[i].a.y)) - 1;//[r[i].a.y, r[i].b.y - 1]全部为1//转换为下标为0开始//[r[i].a.y - 1, r[i].b.y - 2]全部都是1t <<= r[i].a.y - 1;//对于区间[r[i].a.y - 1, ]//r[i].b.y - r[i].a.y = len//(1 << len) - 1先初始先赋值[0, len - 1]全是1//然后区间同时加上,为[r[i].a.y - 1, r[i].a.y - 1 + len - 1]//大矩形一行的状态为[0, cnty - 1]//所以往上移动一行为 << (1 * (cnty - 1))lop(j, r[i].a.x - 1, r[i].b.x - 1){//区间[r[i].a.x, b[i].b.x - 1]//0-index为[r[i].a.x - 1, b[i].b.x - 2]mask[i] |= (t << (j * (cnty - 1)));}}

期望dp方程化简

cnt为状态i1的数量

  • f[k]=1+1n∑i=0nf[k∣(1<<i)]f[k]=1+\cfrac{1}{n}\sum_{i=0}^{n}f[k\mid(1<<i)]f[k]=1+n1​∑i=0n​f[k∣(1<<i)],111表示固定的染色步数花费
  • f[k]=1+cntnf[k]+1n∑(k&(1<<i))==0f[k∣(1<<i)]f[k]=1+\cfrac{cnt}{n}f[k]+\cfrac{1}{n}\sum_{(k\&(1<<i))==0}f[k|(1<<i)]f[k]=1+ncnt​f[k]+n1​∑(k&(1<<i))==0​f[k∣(1<<i)]
  • n−cntnf[k]=1+1n∑(k&(1<<i))==0f[k∣(1<<i)]\cfrac{n-cnt}{n}f[k]=1+\cfrac{1}{n}\sum_{(k\&(1<<i))==0}f[k|(1<<i)]nn−cnt​f[k]=1+n1​∑(k&(1<<i))==0​f[k∣(1<<i)]
  • f[k]=(1+1n∑(k&(1<<i))==0f[k∣(1<<i)])×nn−cntf[k]=(1+\cfrac{1}{n}\sum_{(k\&(1<<i))==0}f[k|(1<<i)])\times\cfrac{n}{n-cnt}f[k]=(1+n1​∑(k&(1<<i))==0​f[k∣(1<<i)])×n−cntn​

完整的注释代码

#include <bits/stdc++.h>
using namespace std;
#define el '\n'
#define pb push_back
#define x first
#define y second
#define rep(i, a, b) for (int i = (a); i <= (b); i++)
#define lop(i, a, b) for (int i = (a); i < (b); i++)
#define dwn(i, a, b) for (int i = (a); i >= (b); i--)typedef long long LL;
typedef pair<int, int> PII;struct read
{static const int M = 1 << 21;char buf[M], *S = buf, *P = buf, c, f;inline char getc(){return (S == P && (P = (S = buf) + fread(buf, 1, 1 << 21, stdin), S == P) ? EOF : *S++);}template <typename T>read &operator>>(T &x){for (c = 0; !isdigit(c); c = getc())f = c;for (x = 0; isdigit(c); c = getc())x = x * 10 + (c - '0');return x = (f ^ '-') ? x : -x, *this;}
} fin;constexpr int N = 23, M = 2e6 + 10, B = 10, md = 998244353;
const double PI = acos(-1), eps = 1e-8;int T, n, m;
int w, h, cntx, cnty;
int f[1 << B];
int xs[N], ys[N];int fpow(int a, int b)
{LL res = 1;while (b){if (b & 1)res = res * a % md;b >>= 1;a = 1LL * a * a % md;}return res;
}struct Rect
{PII a, b;
} r[15];int inv[N];
int k;
bitset<500> mask[10], state;
//mask表示覆盖的二维格子的一维形式void dfs(int u, int s)
{if(u == n){//0-idx,边界f[s] = (state.count() == k) ? 0 : - 1;//计算1的数量是否为k,即是否全部染黑了return;}bitset<500> bk = state;//递归保留现场//不取第u个dfs(u + 1, s);state = bk;//还原state |= mask[u];//取第u个dfs(u + 1, s | (1 << u));return ;
}int main()
{rep(i, 1, 19){inv[i] = fpow(i, md - 2);}fin >> T;while (T--){fin >> n >> w >> h;cntx = cnty = 0;lop(i, 0, n){fin >> r[i].a.x >> r[i].a.y >> r[i].b.x >> r[i].b.y;if (r[i].a.x > w)r[i].a.x = w;if (r[i].a.y > h)r[i].a.y = h;if (r[i].b.x > w)r[i].b.x = w;if (r[i].b.y > h)r[i].b.y = h;xs[++cntx] = r[i].a.x;xs[++cntx] = r[i].b.x;ys[++cnty] = r[i].a.y;ys[++cnty] = r[i].b.y;}sort(xs + 1, xs + cntx + 1);sort(ys + 1, ys + cnty + 1);cntx = unique(xs + 1, xs + cntx + 1) - (xs + 1);cnty = unique(ys + 1, ys + cnty + 1) - (ys + 1);k = (cntx - 1) * (cnty - 1);bitset<500> t;//二维平面转换为一维//虽然22个坐标// 21 * 21个格子看看是否都能染满lop(i, 0, n){r[i].a.x = lower_bound(xs + 1, xs + cntx + 1, r[i].a.x) - xs;r[i].a.y = lower_bound(ys + 1, ys + cnty + 1, r[i].a.y) - ys;r[i].b.x = lower_bound(xs + 1, xs + cntx + 1, r[i].b.x) - xs;r[i].b.y = lower_bound(ys + 1, ys + cnty + 1, r[i].b.y) - ys;mask[i].reset();//t.reset();//标记一个格子被染黑,表示这个格子的左下角被染黑t = (1 << (r[i].b.y - r[i].a.y)) - 1;//[r[i].a.y, r[i].b.y - 1]全部为1//转换为下标为0开始//[r[i].a.y - 1, r[i].b.y - 2]全部都是1t <<= r[i].a.y - 1;//对于区间[r[i].a.y - 1, ]//r[i].b.y - r[i].a.y = len//(1 << len) - 1先初始先赋值[0, len - 1]全是1//然后区间同时加上,为[r[i].a.y - 1, r[i].a.y - 1 + len - 1]//大矩形一行的状态为[0, cnty - 1]//所以往上移动一行为 << (1 * (cnty - 1))lop(j, r[i].a.x - 1, r[i].b.x - 1){//区间[r[i].a.x, b[i].b.x - 1]//0-index为[r[i].a.x - 1, b[i].b.x - 2]mask[i] |= (t << (j * (cnty - 1)));}}state.reset();dfs(0, 0);if(f[(1 << n) - 1] == -1){puts("-1");continue;}//进行逆推期望dp过程dwn(i, (1 << n) - 1, 0){if(f[i] != -1)continue;//f[i] == -1 是终点,期望步数为0int cnt = 0, res = 0;lop(j, 0, n){if(i >> j & 1)cnt ++; //有 cnt / n种情况会转移到自身else res = (res + 1LL * inv[n] * f[i | (1 << j)]) % md;}f[i] = (1LL + res) * n % md * inv[n - cnt] % md;}cout << f[0] << el;}
}

第46届ICPC东亚洲区域赛(昆明)B Blocks题解相关推荐

  1. 第 45 届国际大学生程序设计竞赛(ICPC)亚洲区域赛(济南)(重现赛)

    第 45 届国际大学生程序设计竞赛(ICPC)亚洲区域赛(济南)(重现赛) 导语 涉及的知识点 题目 C D G J M 参考文献 导语 日常的队内集训,开始的时候状态其实很好,但是到了后两题就出现了 ...

  2. 第 45 届国际大学生程序设计竞赛(ICPC)亚洲区域赛(南京)签到题K Co-prime Permutation,L Let‘s Play Curling

    序 emmm因为没时间补题(虽然签到有四题),所以只能先放两个签到. 这是比赛链接:https://ac.nowcoder.com/acm/contest/10272 这是题解链接:2020年ICPC ...

  3. 第 46 届国际大学生程序设计竞赛(ICPC)亚洲区域赛(南京),签到题5题

    文章目录 A.Oops, It's Yesterday Twice More M.Windblume Festival C.Klee in Solitary Confinement H.Crystal ...

  4. 第 46 届国际大学生程序设计竞赛(ICPC)亚洲区域赛(沈阳),签到题5题

    文章目录 E.Edward Gaming, the Champion F.Encoded Strings I B.Bitwise Exclusive-OR Sequence J.Luggage Loc ...

  5. 第 46 届国际大学生程序设计竞赛(ICPC)亚洲区域赛(昆明),签到题3题

    文章目录 K.King of Gamers D.Divisions F.Find the Maximum 补题链接:https://ac.nowcoder.com/acm/contest/32708 ...

  6. 第 46 届国际大学生程序设计竞赛(ICPC)亚洲区域赛(上海),签到题6题

    文章目录 E.Strange Integers D.Strange Fractions G.Edge Groups I.Steadily Growing Steam H.Life is a Game ...

  7. 第 45 届国际大学生程序设计竞赛(ICPC)亚洲区域赛(昆明),签到题HIL

    H. Hard Calculation 链接:https://ac.nowcoder.com/acm/contest/12548/H 来源:牛客网 题目描述 Hooray! It is the fir ...

  8. 第 45 届国际大学生程序设计竞赛(ICPC)亚洲区域赛(昆明),签到题4题

    文章目录 H. Hard Calculation I. Mr. Main and Windmills L. Simone and graph coloring J.Parallel Sort 补题链接 ...

  9. 【第 45 届国际大学生程序设计竞赛(ICPC)亚洲区域赛】Simone and Graph Coloring

    #include <bits/stdc++.h> using namespace std; const int maxn = 1000005, INF = 0x7f7f7f7f; int ...

最新文章

  1. linux shell 算术运算{expr、bc、dc、(( ))和[ ]}
  2. Spring Boot使用@Async实现异步调用:自定义线程池
  3. Java Web 高性能开发,前端的高性能
  4. 使用高级视频质量工具 AVQT 评估视频 | WWDC 演讲实录
  5. 算法练习day17——190405
  6. LiveVideoStack线上分享第三季(六):深度学习与视频编码
  7. 编译选项—微软官方+各地总结
  8. Codeforces Good Bye 2015 A. New Year and Days 水题
  9. Bootstrap实现弹出框和提示框效果代码
  10. 科普 | “开放知识”的定义
  11. 网页版blast构建
  12. vue 代理设置 访问图片_详解Vue源码之数据的代理访问
  13. python定义变量名的时候、需要注意问题_第39p,Python模块的名称空间问题,应该讲完了吧...
  14. linux下声卡的安装
  15. Mac上crontab与/etc/crontab定时任务
  16. Excel 动态透视表
  17. 上海二手房价数据分析
  18. IEEE年度薪酬报告发布!美国程序员薪资中位数7年来首次下降2.4万
  19. 腾讯的职级系统——看清自己的职场宿命
  20. windows开启远程连接

热门文章

  1. 【蓝桥杯预备营集结十一】软件类 C/C++ 预备试题分析及解答
  2. 思考与分析:中国黑客的现状与发展(转)
  3. 中石油问题 K: ABBA(组合数学)
  4. ACC——carsim与simulink联合仿真
  5. Ubuntu Linux 3D桌面完全教程 Ubuntu Linux 3D桌面完全教程
  6. c++学习笔记- 自制魔兽显血改键
  7. 步步高应届生解约事件
  8. 手机php开发工具_最热门的PHP开发工具
  9. 磊科nw336+linux驱动程序,磊科nw336无线网卡驱动,详细教您磊科nw336无线网卡驱动...
  10. 如何搭建Java平台