2026/4/6 2:31:52
网站建设
项目流程
水果电子商务网站建设规划书,wordpress3.9界面中文,知名的网站制作,233建筑网校【题目描述】Alice和Bob玩了一个古老的游戏#xff1a;首先画一个n n的点阵#xff08;下图n 3#xff09;接着#xff0c;他们两个轮流在相邻的点之间画上红边和蓝边#xff1a;直到围成一个封闭的圈#xff08;面积不必为1#xff09;为止#xff0c;“封圈”的那个…【题目描述】Alice和Bob玩了一个古老的游戏首先画一个n × n的点阵下图n 3接着他们两个轮流在相邻的点之间画上红边和蓝边直到围成一个封闭的圈面积不必为1为止“封圈”的那个人就是赢家。因为棋盘实在是太大了(n ≤ 200)他们的游戏实在是太长了他们甚至在游戏中都不知道谁赢得了游戏。于是请你写一个程序帮助他们计算他们是否结束了游戏【输入】输入数据第一行为两个整数n和m。m表示一共画了m条线。以后m行每行首先有两个数字(x, y)代表了画线的起点坐标接着用空格隔开一个字符假如字符是D 则是向下连一条边如果是R 就是向右连一条边。输入数据不会有重复的边且保证正确。【输出】输出一行在第几步的时候结束。假如m步之后也没有结束则输出一行“draw”。【输入样例】3 5 1 1 D 1 1 R 1 2 D 2 1 R 2 2 D【输出样例】41. 题目背景与算法模型核心问题在一个N*N的网格图中判断哪一步连边操作后首次形成环。算法模型连通性维护与判环首选并查集。2. 解法一基于 STL 的直接存储法 (Map Pair)此方法无需推导坐标映射公式适合处理稀疏图或非标准网格完整代码//这道题首先应想到当画一条边前如果find(u)find(v)了那么这条边一画 //就成环了就结束游戏了然后就是想着如何存坐标 两种方式 //第一种直接用pair或者结构体struct自己写一个pair然后存入map但是map是会对键自动排序的 //所以如果用pair就不用管因为pair会按照字典序自动排序但如果自己写结构体 就要重载一下运算符 //第二种直接把二维坐标转换成一维数字把每一个坐标都用一个数字替换 //pair写法 #include bits/stdc.h #include algorithm #include map using namespace std; int n,m; //定义类型别名避免后续反复书写pairint,int typedef pairint,int pii; pii p1; pii p2; mappii,pii fa;//fa存每个坐标的父/祖先节点 pii find(pii x){ if(fa[x]x) return x;//如果已经是祖先/根结点 返回 //否则就递归找祖先 并进行路径压缩 return fa[x]find(fa[x]); } void uni(pii x,pii y){ pii faxfind(x);//x的祖先节点 pii fayfind(y);//y的祖先节点 //如果相等说明在一个集合 无事发生不相等就让fax成为fay的老大的老大 if(fax!fay){ fa[fay]fax; } } int main(){ cinnm; for(int i1;im;i){ int x,y; char c; cinxyc; p1{x,y}; if(cD)//向下 p2{x1,y}; else//向右 p2{x,y1}; //如果p1 p2还没有父节点就初始化父节点为自己 if(!fa.count(p1)) fa[p1]p1; if(!fa.count(p2)) fa[p2]p2; //当画一条边前如果find(u)已经find(v)了那么这条边一画 就成环了 if(find(p1)find(p2)){ couti; return 0; } uni(p1,p2); } coutdraw; return 0; }3. 解法二二维坐标转化为一位标记的数组法这是竞赛中的标准解法通过ID (x-1)*Ny将二维坐标映射为一维效率最高。//第二种方法二维坐标用一维数字代替节省大量代码 #include bits/stdc.h using namespace std; int n,m; int fa[40010]; //二维坐标压缩成一维标记 int getid(int x,int y){ return (x-1)*ny; } int find(int x){ if(fa[x]x) return x;//如果已经是祖先/根结点 返回 //否则就递归找祖先 并进行路径压缩 return fa[x]find(fa[x]); } void uni(int x,int y){ int faxfind(x);//x的祖先节点 int fayfind(y);//y的祖先节点 //如果相等说明在一个集合 无事发生不相等就让fax成为fay的老大的老大 if(fax!fay){ fa[fay]fax; } } int main(){ cinnm; //初始化自己的祖先为自己 for(int i1;in*n;i) fa[i]i; for(int i1;im;i){ int x,y; char c; cinxyc; int p1getid(x,y); int p2-1; if(cD)//向下 p2getid(x1,y); else//向右 p2getid(x,y1); //如果p1 p2还没有父节点就初始化父节点为自己 //当画一条边前如果find(u)已经find(v)了那么这条边一画 就成环了 if(find(p1)find(p2)){ couti; return 0; } uni(p1,p2); } coutdraw; return 0; }4. 关键复盘STL 写法中的严重易错点在使用第一种方法Map Pair时许多同学会因为不熟悉 C 强类型机制而遭遇编译错误或逻辑异常。以下是必须规避的三个核心错误易错点 1错误使用 Pair 作为类型名会导致信息学奥赛一本通system error这是新手最容易犯的语法错误。错误写法pair p1; // ❌ 错误缺少模板参数 pair find(pair x) { // ❌ 错误编译器无法推断 pair 内部存什么 ... }错误原因std::pair本质上是一个类模板而非具体的类型 (Type)。它就像一个模具必须明确告诉编译器里面装的是int、double还是string编译器才能生成具体的代码。正确写法必须显式指定模板参数。pairint,int p1; // ✅ 正确 pairint,int find(pairint,int x) { ... } // ✅ 正确优化建议使用typedef或using简化代码。typedef pairint,int pii; pii find(pii x) { ... }易错点 2Map 的自动构造陷阱错误现象没有对 map 进行初始化直接在find函数中访问fa[x]。后果当访问不存在的键时std::map会自动插入该键并将其值初始化为默认值{0,0}。这会导致所有未手动初始化的节点其父节点都被错误地指向{0,0}破坏并查集的树形结构。修正方案在调用find前必须使用if(!fa.count(p))检查并手动初始化fa[p] p;。易错点 3并查集路径压缩的浅拷贝问题错误写法void uni(pii x,pii y) {fa[y]fa[x];}分析这行代码并没有去寻找x和y的根节点祖宗仅仅是将y的父节点修改了。这在路径压缩未完成时是错误的会导致集合无法正确合并。正确写法必须调用find函数获取根节点。pii faxfind(x); pii fayfind(y); if(fax!fay) fa[fay]fax;5. 总结本题通过两种解法展示了数据结构选择的权衡数组法利用数学映射实现O(1)访问是处理标准网格图的最优解。STL 法代码逻辑直观但要求对C 模板语法和容器机制有一定理解否则极易出现编译错误或隐蔽的运行时错误。