写在前面

UVA的题需要自己读入一个 \(T\) 组数据,别被样例给迷惑了

Solution

每个格子只有两种填法且 \(n \le 7\),暴力搜索两种填法,开cnt数组统计连接个数。

填一个格子,如果是 "\",格子左上角和右下角的 \(cnt++\),如果是 "/",格子左下角和右上角的 \(cnt++\)。只有更改后的 \(cnt\) 小于等于目标 \(cnt\)才继续向下搜,否则回溯

发现每填一个格子,连接格子左上角的格点的个数就可以被确定,那么只有左上角的格点个数等于目标格点个数或没有要求才继续搜索,否则回溯

如果搜索到第 \(n + 1\) 列时,要额外判断边界第 \(n + 1\) 列的 \(cnt\)是否满足对应的个数

如果搜索到第 \(n\) 行时,要额外判断边界第 \(n + 1\) 行的 \(cnt\) 是否满足对应个数

如何保证无环?不难想到,只有在填 "/" 时才有可能出现环,那么在填 "/" 之前,先判断是否有环

如何处理点的坐标?把行看做十位,把列看做个位就好啦

  • 算法一:考虑可撤销并查集,然而我不会

  • 算法二:发现n很小,每次判断时 \(n^2\) 扫一遍建图,在 \(dfs\) 看看能否从左下角跑到右上角

  • 算法三:很显然算法二很傻逼,直接用并查集维护就好,加完边后判断左下角和右上角是否在同一并查集里,省去 \(dfs\) 的时间,注意清零!

最后输出方案就好啦

Code

我一开始建图跑的,后来也没改(因为懒

/*
Work by: Suzt_ilymics
Knowledge: ??
Time: O(??)
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long
#define orz cout<<"lkp AK IOI!"<<endl using namespace std;
const int MAXN = 10;
const int INF = 1;
const int mod = 1; struct edge{
int from, to, nxt;
}e[10100 << 1];
int head[MAXN * MAXN], num_edge = 0; int n;
int go[MAXN][MAXN];
int cnt[MAXN][MAXN], now[MAXN][MAXN];
bool flag = false, Flag = false; int read(){
int s = 0, f = 0;
char ch = getchar();
while(!isdigit(ch)) f |= (ch == '-'), ch = getchar();
while(isdigit(ch)) s = (s << 1) + (s << 3) + ch - '0' , ch = getchar();
return f ? -s : s;
} void add_edge(int from, int to){
e[++num_edge] = (edge){from, to, head[from]}, head[from] = num_edge;
} bool bl(int u, int fa, int end){
for(int i = head[u]; i != -1; i = e[i].nxt){
int v = e[i].to;
if(v == fa) continue;
if(v == end) {
Flag = 1;
return true;
}
bl(v, u, end);
if(Flag) { return true; }
}
return false;
} bool pd(int sx, int sy, int ex, int ey){
memset(head, -1, sizeof(head)); num_edge = 0;
Flag = false;
for(int i = 1; i <= n; ++i){
for(int j = 1; j <= n; ++j){
if(now[i][j] == 0){
add_edge(i * 10 + j, (i + 1) * 10 + j + 1);
add_edge((i + 1) * 10 + j + 1, i * 10 + j);
}
if(now[i][j] == 1){
add_edge((i + 1) * 10 + j, i * 10 + j + 1);
add_edge(i * 10 + j + 1, (i + 1) * 10 + j);
}
}
}
if(bl(sx * 10 + sy, 0, ex * 10 + ey)) return 1;
else return 0;
} void dfs(int posx, int posy){
// cout<<posx<<" "<<posy;
// orz;
if(posx == n && posy == n + 1) {
if( ((cnt[posx + 1][posy] == go[posx + 1][posy]) || (go[posx + 1][posy] == 9)) && ((cnt[posx][posy] == go[posx][posy]) || (go[posx][posy] == 9)) ) flag = 1;
return ;
}// 如果搜到最后一个点,说明已经找到答案。退出
if(posy == n + 1){ //如果这一行搜完了
if((cnt[posx][posy] == go[posx][posy]) || (go[posx][posy] == 9) ) posx++, posy = 1;//换行
else return ;// 如果已经确定的那个数并没有达到目标,返回
}// now[posx][posy] = 0;// 填 "\"
cnt[posx][posy]++, cnt[posx + 1][posy + 1]++;// 对应位置加1 if(cnt[posx][posy] <= go[posx][posy] && cnt[posx + 1][posy + 1] <= go[posx + 1][posy + 1]) {//如果两个对应位置大于目标位置就不向下搜索
if((go[posx][posy] != 9 && go[posx][posy] == cnt[posx][posy]) || (go[posx][posy] == 9)) {//如果已经确定的那个数没有达到目标,停止向下搜索
if((posx != n) || (posx == n && ( (go[posx + 1][posy] != 9 && go[posx + 1][posy] == cnt[posx + 1][posy]) || (go[posx + 1][posy] == 9) ) )){
dfs(posx, posy + 1);//
}
}
}//
if(flag) return ;// 如果找到答案就返回
cnt[posx][posy]--, cnt[posx + 1][posy + 1]--;//回溯 if(pd(posx + 1, posy, posx, posy + 1)){ return ;} now[posx][posy] = 1;// 填 "/"
cnt[posx + 1][posy]++, cnt[posx][posy + 1]++;// 对应位置加1 if(cnt[posx + 1][posy] <= go[posx + 1][posy] && cnt[posx][posy + 1] <= go[posx][posy + 1]) {//如果两个对应位置大于目标位置就不向下搜索
if((go[posx][posy] != 9 && go[posx][posy] == cnt[posx][posy]) || (go[posx][posy] == 9)) {//如果已经确定的那个数没有达到目标,停止向下搜索
if((posx != n) || (posx == n && ( (go[posx + 1][posy] != 9 && go[posx + 1][posy] == cnt[posx + 1][posy]) || (go[posx + 1][posy] == 9) ) )){
dfs(posx, posy + 1);//
}
}
}
if(flag) return ;// 如果找到答案就返回
now[posx][posy] = -1;//回溯
cnt[posx + 1][posy]--, cnt[posx][posy + 1]--;// 回溯
} int main()
{
// freopen("gokigen.in","r",stdin);
// freopen("gokigen.out","w",stdout);
int T;
T = read();
while(T--){
n = read();
memset(now, -1, sizeof(now));
memset(cnt, 0, sizeof(cnt));
memset(go, 0, sizeof(go));
flag = 0;
char ch[10];
for(int i = 1; i <= n + 1; ++i){
cin>>(ch + 1);
for(int j = 1; j <= n + 1; ++j){
if(isdigit(ch[j])) go[i][j] = ch[j] - '0';
else go[i][j] = 9;
}
} dfs(1, 1);
// for(int i = 1; i <= n + 1; ++i){
// for(int j = 1; j <= n + 1; ++j){
// cout<<go[i][j]<<" ";
// }
// cout<<"\n";
// }
// cout<<"\n";
//
// for(int i = 1; i <= n + 1; ++i){
// for(int j = 1; j <= n + 1; ++j){
// cout<<cnt[i][j]<<" ";
// }
// cout<<"\n";
// }
// cout<<"\n"; for(int i = 1; i <= n; ++i){
for(int j = 1; j <= n; ++j){
if(now[i][j] == 1) cout<<"/";
else if(now[i][j] == 0) cout<<"\\";
else cout<<"s";
}
cout<<"\n";
}
}
return 0;
}

UVA11694 Gokigen Naname题解的更多相关文章

  1. 题解 UVA11694 【Gokigen Naname谜题 Gokigen Naname】

    题目 题解 考场上连暴力都不会打的码农题,深搜是真的难 /kk 前置问题 怎么输出"\" cout<<"\\"; 2.怎么处理不在一个环里,可以考虑 ...

  2. Uva 11694 Gokigen Naname

    基本思路是Dfs: 1. 一个一个格子摆放,以每个各自的左上角的点为基准点代表格子,比如(0,0)代表(0,0)(0,1)(1,0)(1,1)组成的格子,(0,1)代表(0,1)(0,2)(1,1), ...

  3. UVA11694-Gokigen Naname(DFS进阶)

    Problem UVA11694-Gokigen Naname Accept: 76   Submit: 586Time Limit: 10000 mSec Problem Description I ...

  4. 2016 华南师大ACM校赛 SCNUCPC 非官方题解

    我要举报本次校赛出题人的消极出题!!! 官方题解请戳:http://3.scnuacm2015.sinaapp.com/?p=89(其实就是一堆代码没有题解) A. 树链剖分数据结构板题 题目大意:我 ...

  5. noip2016十连测题解

    以下代码为了阅读方便,省去以下头文件: #include <iostream> #include <stdio.h> #include <math.h> #incl ...

  6. BZOJ-2561-最小生成树 题解(最小割)

    2561: 最小生成树(题解) Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1628  Solved: 786 传送门:http://www.lyd ...

  7. Codeforces Round #353 (Div. 2) ABCDE 题解 python

    Problems     # Name     A Infinite Sequence standard input/output 1 s, 256 MB    x3509 B Restoring P ...

  8. 哈尔滨理工大学ACM全国邀请赛(网络同步赛)题解

    题目链接 提交连接:http://acm-software.hrbust.edu.cn/problemset.php?page=5 1470-1482 只做出来四道比较水的题目,还需要加强中等题的训练 ...

  9. 2016ACM青岛区域赛题解

    A.Relic Discovery_hdu5982 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Jav ...

随机推荐

  1. 读取pdf中的内容

    import com.spire.pdf.PdfDocument;import com.spire.pdf.PdfPageBase;import java.io.*; public class Ext ...

  2. java: Compilation failed: internal java compiler error

    IDEA 编译项目出现java: Compilation failed: internal java compiler error 原因:  项目Java版本不一致 解决办法:  点击FIle> ...

  3. 自动化单元测试(Karma + Mocha)

    使用 Karma + Mocha做单元测试 Karma([ˈkɑrmə] 卡玛)是一个测试运行器,它可以呼起浏览器,加载测试脚本,然后运行测试用例 Mocha([ˈmoʊkə] 摩卡)是一个单元测试框 ...

  4. Lightweight Render Pipeline

    (翻译) Lightweight Render Pipeline (LWRP),轻量级渲染管线,是一个Unity预制的Scriptable Render Pipeline (SRP).LWRP可以为移 ...

  5. 整数划分(硬币问题)(dp)

    题目描述 考试时思路 本菜狗考试的时候,第一扁打了纯dfs,15分拿了9分 后面看了时限400ms,多组数据,以为会卡常数,然后就想着先dp打表然后再直接O(1)查询 后面发现自己想多了,数据有点水- ...

  6. python第一节:变量及数据类型

    一.变量 1.什么是变量 变:即为变化的事物 量:即为事物当前的状态 2.为什么用变量 变量可以方便的记录事物当前状态,在后面随时可以调出使用 3.怎么用变量 变量使用前需要先进行赋值(记录状态) 赋 ...

  7. 「珍贵历史资料鉴赏」CF786B 题解

    写在前面 偶然翻到一篇 2019-08-07 18:58 写的未发布的题解. 给大家找点乐子玩. 正文 知识点:线段树优化建图 线段树优化建图 用于解决 类似 从 x 向区间[L,R]的 区间连边问题 ...

  8. springboot源码解析-管中窥豹系列之Runner(三)

    一.前言 Springboot源码解析是一件大工程,逐行逐句的去研究代码,会很枯燥,也不容易坚持下去. 我们不追求大而全,而是试着每次去研究一个小知识点,最终聚沙成塔,这就是我们的springboot ...

  9. 【递归】P5461赦免战俘

    题目相关 原题链接:P5461 赦免战俘 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 题目背景 借助反作弊系统,一些在月赛有抄袭作弊行为的选手被抓出来了! 题目描述 现有 \(2 ...

  10. .NET 云原生架构师训练营(模块二 基础巩固 RabbitMQ Masstransit 详解)--学习笔记

    2.6.7 RabbitMQ -- Masstransit 详解 Consumer 消费者 Producer 生产者 Request-Response 请求-响应 Consumer 消费者 在 Mas ...