SGU[101] Domino

Description

描述

Dominoes – game played with small, rectangular blocks of wood or other material, each identified by a number of dots, or pips, on its face. The blocks usually are called bones, dominoes, or pieces and sometimes men, stones, or even cards.

The face of each piece is divided, by a line or ridge, into two squares, each of which is marked as would be a pair of dice...

The principle in nearly all modern dominoes games is to match one end of a piece to another that is identically or reciprocally numbered.

ENCYCLOPÆDIA BRITANNICA

多米诺——使用小的、矩形木块或者其它材料,每个块的面上标有点。这样的块通常被称作骨牌,多米诺骨牌,或者片条。有时候使用人、骨牌,甚至卡片。

每个块被一条直线或者分为两面,每一面上都标记上了一对骰子...

在现代多米诺游戏中,规则是使得两个标号相同或对应的两个骨牌首尾相连。

——《大英百科全书》

Given a set of domino pieces where each side is marked with two digits from 0 to 6. Your task is to arrange pieces in a line such way, that they touch through equal marked sides. It is possible to rotate pieces changing left and right side.

给定一系列的多米诺骨牌,每一面都被标记了两个从0到6的数字。你的任务是安排这样的序列,使得骨牌的左右相连,且相连面的数字相同。骨牌可以进行翻转,使得左右的数字交换。

Input

输入

The first line of the input contains a single integer N (1 ≤ N ≤ 100) representing the total number of pieces in the domino set. The following N lines describe pieces. Each piece is represented on a separate line in a form of two digits from 0 to 6 separated by a space.

输入的第一行包含一个整数N (1 <= N <= 100) 代表多米诺骨牌的总数。接下来的N行描述骨牌的状态。每一行包含两个从0到6的数字。

Output

输出

Write “No solution” if it is impossible to arrange them described way. If it is possible, write any of way. Pieces must be written in left-to-right order. Every of N lines must contains number of current domino piece and sign “+” or “-“ (first means that you not rotate that piece, and second if you rotate it).

如果不存在这样的排列,输出“No solution”。如果存在这样的排列,输出任何一种情形。请必须从左到右输出,输出共N行,每一行包含一个当前多米诺骨牌的编号,以及一个标记“+”或“-”(“+”代表不反转该骨牌,“-”代表反转该骨牌)。

Sample Input

样例输入

5
1 2
2 4
2 4
6 4
2 1

Sample Output

样例输出

2 -
5 +
1 +
3 +
4 -

Analysis

分析

这道题目做了好久好久,终于AC了。

我第一次看到这道题目完全不知道怎么做,第二次觉得可以dfs。后来看了题解,发现是欧拉通路。

我们将0-6这7个数字看成点,每个多米诺骨牌看成一条无向边,构建一张图。

这边用到一个trick,我们设置pVisited数组的时候,不一定要判断点是否访问过,我们也可以用来判断边是否访问过,这样我们就可以使用边集数组来保存这张图。

欧拉通路也就是一笔画问题,它区别于欧拉回路(欧拉回路要求回到起始点)。

思路很简单,首先确定起点:

  • 度为奇数的点的总数为0,任选一个点为起点;
  • 度为奇数的点的总数为2,任选两个点中的某个点为起点;
  • 其他情况下无解。

接下来就是写欧拉通路了,之前在一个NOIP的参考资料上看到一个dfs的版本,按着它写了一遍,一直WA,后来发现,他的方法好像有问题。

除此之外,还需要判断自环,也就是如果这张图不连通,那么显然是无解的。

还有,选择起点的时候,任意返回一个点,需要注意这个点必须是出现过的点,否则就会WA。

经过这么多的思考,重新写了不知道多少遍代码,终于AC了。

最后还在“No solution”中“s”的大小写问题上PE了一次。

Solution

解决方案

#include <iostream>
#include <memory.h>

using namespace std;

const int MAX = 128;
const int SIZE = 8;

struct Node
{
	int s, e;
};

struct Path
{
	int x;
	char y;
};

int N;
bool bFlag;
bool pVisited[MAX];
int pDegree[SIZE], pMap[SIZE][SIZE];
Node pNode[MAX];
Path pPath[MAX];

int Check();
void dfs(int nStart, int nFlag, int nStep);

int main()
{
	int x, y;
	while(cin >> N)
	{
		bFlag = false;
		memset(pMap, 0, sizeof(pMap));
		memset(pVisited, false, sizeof(pVisited));
		for(int i = 1; i <= N; i++)
		{
			cin >> x >> y;
			pMap[x][y]++; pMap[y][x]++;
			pNode[i].s = x; pNode[i].e = y;
		}
		int nStart = Check();
		if(nStart == -1) {  cout << "No solution" << endl; }
		else
		{
			for(int i = 1; i <= N; i++)
			{
				if(pNode[i].s == nStart)
				{ dfs(i, 1, 1); break; }
				else if(pNode[i].e == nStart)
				{ dfs(i, 2, 1); break; }
			}
		}
		if(!bFlag) { cout << "No solution" << endl; }
	}
}

int Check()
{
	memset(pDegree, 0, sizeof(pDegree));
	int nCnt = 0, nPos = pNode[1].s;
	for(int i = 0; i < SIZE; i++)
	{
		for(int j = 0; j < SIZE; j++)
		{ pDegree[i] += pMap[i][j]; }
	}
	for(int i = 0; i < SIZE; i++)
	{
		if(pDegree[i] % 2) { nCnt++; nPos = i; }
	}
	if(nCnt == 0 || nCnt == 2) { return nPos; }
	else { return -1; }
}

void dfs(int nStart, int nFlag, int nStep)
{
	if(bFlag) { return; }
	pVisited[nStart] = true;
	pPath[nStep].x = nStart;
	pPath[nStep].y = (nFlag == 1) ? ‘+‘ : ‘-‘;
	if(nStep == N)
	{
		for(int i = 1; i <= N; i++)
		{ cout << pPath[i].x << " " << pPath[i].y << endl; }
		bFlag = true;
	}
	int nNext = (nFlag == 1) ? pNode[nStart].e : pNode[nStart].s;
	for(int i = 1; i <= N; i++)
	{
		if(!pVisited[i])
		{
			if(pNode[i].s == nNext) { dfs(i, 1, nStep + 1); }
			else if(pNode[i].e == nNext) { dfs(i, 2, nStep + 1); }
			pVisited[i] = false;
		}
	}
}

  

终于AC了这道题目,写了好久好久了。

时间: 2024-12-26 10:25:49

SGU[101] Domino的相关文章

SGU 101.Domino( 欧拉路径 )

求欧拉路径...直接dfs即可,时间复杂度O(N) --------------------------------------------------------------------------- #include<cstdio> #include<cstring> #include<algorithm> #include<stack> using namespace std; #define X(i) Edge[i].first #define Y(

SGU 101 Domino 题解

鉴于SGU题目难度较大,AC后便给出算法并发布博文,代码则写得较满意后再补上.——icedream61 题目简述:暂略 AC人数:3609(2015年7月20日) 算法: 这题就是一笔画,最多只有7个点(0~6),每个骨牌就是一条双向边. 要做的,就是找出一条一笔画的路径.步骤如下: 1. 读入数据,建成图. 2. 判断可否一笔画.一笔画条件:奇点数为0或2 + 联通分量数为1. 3. 如果不可一笔画,则输出No solution,结束:如果可以,则找到一条路径R,并输出. 下面给出找一笔画路径

SGU 101. Domino 欧拉回路

无向图欧拉回路 欧拉通路 #include <cstdio> #include <cstring> using namespace std; struct edge { int v, next, b, id; }e[210]; int vis[210]; int first[10], cnt; int ans[210], len; int f[10]; int find(int x) { if(x != f[x]) return f[x] = find(f[x]); return

ACM: SGU 101 Domino- 欧拉回路-并查集

sgu 101 - Domino Time Limit:250MS     Memory Limit:4096KB     64bit IO Format:%I64d & %I64u Description Dominoes – game played with small, rectangular blocks of wood or other material, each identified by a number of dots, or pips, on its face. The bl

SGU 101 题解

#include<iostream> #include<algorithm> using namespace std; struct sticktype { int l; int r; bool vis; }stick[101]; struct pointtype { int amount; int next[7]; bool vis; }point[7]; int tail=0; int queue[201]; void dfs(int p); int main() { int

Domino - SGU 101 (欧拉路径)

题目大意:这是一个多米诺骨游戏,这个游戏的规则就是一个连着一个,现在给出 N 个多米诺,每个多米诺两边都有一个编号,相邻的多米诺的编号要一致,当然多米诺是可以翻转的(翻转就加‘-’,不翻转是‘+’),输出一个多米诺的顺序,要从左往右. 分析:开始的是有以为是二分匹配,然后发现并不能匹配,无法分成两个集合,网络流也不能搞,最后百度才知道是欧拉路径(从一点出发经过所有的路径,每条路只走一次),这个算法倒也不难理解,感觉很巧妙,如果点的入度都是偶数的话,那么就是欧拉回路(可以从一个点出发然后,最后还可

sgu 101 无向图有双重边的欧拉路径

#include <iostream> #include <cstring> #include <cstdlib> #include <cstdio> #include <cmath> #include <queue> #include <stack> #include <algorithm> using namespace std; const int MAXN = 400 + 10; struct Edge

SGU 乱搞日志

SGU 100 A+B :太神不会 SGU 101 Domino: 题目大意:有N张骨牌,两张骨牌有两面有0到6的数字,能相连当且仅当前后数字相同,问能否有将N张骨牌连接的方案?思路:裸的欧拉回路,注意自环,连通 1 //sgu101 2 #include<iostream> 3 #include<cstdio> 4 #include <math.h> 5 #include<algorithm> 6 #include<string.h> 7 #i

今日SGU

SGU 100 题意: 普通的a+b #include<bits/stdc++.h> #define de(x) cout<<#x<<"="<<x<<endl; #define dd(x) cout<<#x<<"="<<x<<" "; #define rep(i,a,b) for(int i=a;i<(b);++i) #define