Usaco Training [1.3] wormhole

传送门

解题要素:代码能力

解题步骤:理解题意 - 》搜索枚举所有可能的配对情况 - 》判断冲突并求解 - 》调试

一. 理解题意

  这里讲几个不容易理解的点:

    1. +x方向 即向右走

    2. 一旦来到虫洞,就必须掉入

二. 搜索枚举所有可能的配对情况

  考虑引入match数组,对于当前的节点来说,枚举后面的点是否已配对过即可

 1 int match[N];
 2 inline void dfs(int x) { //当前节点
 3     if (x == n + 1) {
 4         rep(i, 1, n) if (check(i, i, 1, 0)) {
 5             ans++;
 6             break;
 7         }
 8         return;
 9     }
10     if (match[x]) dfs(x + 1); //已有匹配,无需枚举
11     else {
12         rep(i, x + 1, n) if (!match[i]) { //枚举
13             match[i] = x, match[x] = i;
14             dfs(x + 1);
15             match[i] = match[x] = 0; //回溯
16         }
17     }
18 }

三. 判断冲突并求解

  代码的核心部分,分析当前的一个状态有哪些量是相关的,加上对于题目的理解

 1 int ans;
 2 inline bool check(int begin, int now, int length, int state) { //state - 0 : walk 1 : worm
 3     if (length > 1 && now == begin && state == 0) return 1; //回到原点了,而且是用走的方式
 4     if (state == 0) { //走到虫洞口了就跳进去
 5         check(begin, match[now], length + 1, 1);
 6     }
 7     else { //从虫洞d出来,就往前走,如果前面有虫洞,就走过去,没有就返回0
 8         if (a[now].y == a[now + 1].y) check(begin, now + 1, length + 1, 0); else return 0;
 9     }
10 }

四. 调试

  1.读入的坐标轴是与正常的行列相反的,在排序和判同行时须格外注意

  2.因为奶牛所在初始虫洞处时便掉进去,所以最终只有可能到虫洞处

最终的代码:

 1 /*
 2 PROG: wormhole
 3 LANG: C++
 4 */
 5 #include <bits/stdc++.h>
 6 using namespace std;
 7 #define rep(i, a, b) for(int i = a; i <= b; ++i)
 8
 9 const int N = 20;
10
11 int n;
12 struct node {
13     int x, y;
14 }a[N];
15
16 bool cmp(const node &a, const node &b) {
17     return a.y == b.y ? a.x < b.x : a.y < b.y;
18 }
19
20 int match[N], ans;
21
22 inline bool check(int begin, int now, int length, int state) { //state - 0 : walk 1 : worm
23     if (length > 1 && now == begin && state == 0) return 1;
24     if (state == 0) {
25         check(begin, match[now], length + 1, 1);
26     }
27     else {
28         if (a[now].y == a[now + 1].y) check(begin, now + 1, length + 1, 0); else return 0;
29     }
30 }
31
32 inline void dfs(int x) {
33     if (x == n + 1) {
34         rep(i, 1, n) if (check(i, i, 1, 0)) {
35             ans++;
36             break;
37         }
38         return;
39     }
40     if (match[x]) dfs(x + 1);
41     else {
42         rep(i, x + 1, n) if (!match[i]) {
43             match[i] = x, match[x] = i;
44             dfs(x + 1);
45             match[i] = match[x] = 0;
46         }
47     }
48 }
49
50 int main() {
51     freopen("wormhole.in", "r", stdin);
52     freopen("wormhole.out", "w", stdout);
53     scanf("%d", &n);
54     rep(i, 1, n) {
55         scanf("%d%d", &a[i].x, &a[i].y);
56     }
57     sort(a + 1, a + n + 1, cmp);
58     dfs(1);
59     printf("%d\n", ans);
60     return 0;
61 }

原文地址:https://www.cnblogs.com/Fo0o0ol/p/10018238.html

时间: 2024-08-30 18:21:15

Usaco Training [1.3] wormhole的相关文章

USACO Training完结感想

USACO Training在历经几年时间后终于被我刷完了.其实我很早就已经刷完了,只不过一直拖到今天才发完blog.真是怠惰呢~~~~~ USACO绝对是我成长的记录者,它看着我,从当初初出茅庐的小子一步步走到今天.虽然不能说是什么大犇,但是也是有一定实力的选手. USACO一共有6章.从简易到困难,从整体上来说这个题库不算难.是一个适合新手锻炼的地方.当然里面也有很多比较经典的题目. 它一直陪伴着我的成长,正如一只COW一样哺育了我. 如果完成前3章已经可以在NOIP中得到不错的成绩了,但是

USACO Training Section 3.1 Contact

P2724 联系 Contact 题目背景 奶牛们开始对用射电望远镜扫描牧场外的宇宙感兴趣.最近,他们注意到了一种非常奇怪的脉冲调制微波从星系的中央发射出来.他们希望知道电波是否是被某些地外生命发射出来的,还是仅仅是普通的的星星发出的 题目描述 帮助奶牛们用一个能够分析他们在文件中记下的记录的工具来找到真相.他们在寻找长度在A到B之间(包含A和B本身)在每天的数据文件中重复得最多的比特序列 (1 <= A <= B <= 12).他们在找那些重复得最多的比特序列.一个输入限制告诉你应输出

LuoGu 1200 你的飞碟在这儿 &amp;&amp; USACO Training Section 1.1_1

描述 众所周知,在每一个彗星后都有一只UFO.这些UFO时常来收集地球上的忠诚支持者.不幸的是,他们的飞碟每次出行都只能带上一组支持者.因此,他们要用 一种聪明的方案让这些小组提前知道谁会被彗星带走.他们为每个彗星起了一个名字,通过这些名字来决定这个小组是不是被带走的那个特定的小组(你认为是谁给 这些彗星取的名字呢?).关于如何搭配的细节会在下面告诉你:你的任务是写一个程序,通过小组名和彗星名来决定这个小组是否能被那颗彗星后面的UFO带 走. 小组名和彗星名都以下列方式转换成一个数字:最终的数字

USACO Training Section3.1 Score Inflation

我们可以从几个种类中选取竞赛的题目,这里的一个"种类"是指一个竞赛题目的集合,解决集合中的题目需要相同多的时间并且能得到相同的分数.你的任务是写一个程序来告诉USACO的职员,应该从每一个种类中选取多少题目,使得解决题目的总耗时在竞赛规定的时间里并且总分最大.输入包括竞赛的时间,M(1 <= M <= 10,000)和N,"种类"的数目1 <= N <= 10,000.后面的每一行将包括两个整数来描述一个"种类": 第一个

LuoGu 1201 贪婪的送礼者 &amp;&amp; USACO Training Section 1.1_2

描述 对于一群(NP个)要互送礼物的朋友,GY要确定每个人送出的钱比收到的多多少. 在这一个问题中,每个人都准备了一些钱来送礼物,而这些钱将会被平均分给那些将收到他的礼物的人. 然而,在任何一群朋友中,有些人将送出较多的礼物(可能是因为有较多的朋友),有些人有准备了较多的钱. 给出一群朋友,没有人的名字会长于 14 字符,给出每个人将花在送礼上的钱,和将收到他的礼物的人的列表, 请确定每个人收到的比送出的钱多的数目. 格式 PROGRAM NAME: gift1 INPUT FORMAT: (f

LuoGu 1202 黑色星期五 &amp;&amp; USACO Training Section 1.1_3

描述 13号又是一个星期五.13号在星期五比在其他日子少吗?为了回答这个问题,写一个程序,要求计算每个月的十三号落在周一到周日的次数.给出N年的 一个周期,要求计算1900年1月1日至1900+N-1年12月31日中十三号落在周一到周日的次数,N为正整数且不大于400. 注意,开始今年是一千九百年,不是1990 这里有一些你要知道的: 1.1900年1月1日是星期一. 2.4,6,11和9月有30天.其他月份除了2月都有31天.闰年2月有29天,平年2月有28天. 3.年份可以被4整除的为闰年(

USACO training 2.4.5 Fractions to Decimals题解

嗯...用到一个定理,对于一个最简分数n/d,d=(2^x)*(5^y)*m,m≠1,那么其循环节长度为使10^L mod m==1的最小的L,不循环长度为max(x,y) 然后这题就没什么了.. 76个字符一换行比较坑,我用了stringstream... 1 #include<iostream> 2 #include<sstream> 3 #include<cstdio> 4 #include<iomanip> 5 #include<algorit

最小生成树基础模板题(USACO Training Section 3.1 最短网络 Agri-Net)

农民约翰被选为他们镇的镇长!他其中一个竞选承诺就是在镇上建立起互联网,并连接到所有的农场.当然,他需要你的帮助. 约翰已经给他的农场安排了一条高速的网络线路,他想把这条线路共享给其他农场.为了用最小的消费,他想铺设最短的光纤去连接所有的农场. 你将得到一份各农场之间连接费用的列表,你必须找出能连接所有农场并所用光纤最短的方案.每两个农场间的距离不会超过100000 输入格式: 第一行: 农场的个数,N(3<=N<=100). 第二行..结尾: 后来的行包含了一个N*N的矩阵,表示每个农场之间的

【COGS &amp; USACO Training】710. 命名那个数字(hash+水题+dfs)

http://cojs.tk/cogs/problem/problem.php?pid=710 近日开始刷水... 此题我为了练一下hash...但是hash跑得比暴力还慢.. 不言而喻... #include <cstdio> #include <cstring> #include <cmath> #include <string> #include <iostream> #include <algorithm> #include