SGU 101 Domino 翻译 题解

101. 多米诺

每个测试点时间限制: 0.50 sec
每个测试点内存限制: 4096 KB

多米诺 ——一种用木头或者其他材料做的小方块进行的游戏,其中每个小方块面上通常标记点数或分数。这些小方块被称作骨牌,多米诺。有时用骨片,用人,甚至用卡片。
每个小块的表面被一条线分割成两部分,每一部分都写上了可能成对的号码。

在差不多所有的现代多米诺骨牌游戏中,比赛原则是要使两个标有相同或成对的号码的小方块首尾相接应。

——《大英百科全书》

给你一些多米诺骨牌,每块的两部分都标记上 0 到 6 的号码,你的任务是把这些骨牌排列在一条直线上,使得相邻骨牌的相邻部分有同样的号码。骨牌可以左右翻转。

输入

第一行包括一个整数 N (1 ≤ N ≤ 100) 表示骨牌总数。接下来 N 行描述每一块骨牌两部分的号码,每行两个 0 - 6 的数,用空格隔开。

输出

如果不存在这样的方案,输出 “No solution”。如果方案存在,输出任意一种符合要求的方案。输出方案时应该从左到右描述骨牌的排列,每行输出用空格隔开的一个整数和一个字符,分别表示骨牌的编号和是否翻转骨牌,(+表示不翻转,-表示翻转)。

样例输入

5
1 2
2 4
2 4
6 4
2 1

样例输出

2 -
5 +
1 +
3 +
4 -

================================华丽的分割线 ================================

  要上学了,下午回来再发。 2011年6月4日 14时00分45秒
  要注意到这个可以转换成为图,最开始我计划使用骨牌作为节点,但是发现数据处理太麻烦了,第一节点数目多,第二每添加一个新骨牌处理都可能是O(n^2)的数量级,所以一直没有动手(如果要写可能不一定需要O(n^2)的数量级处理输入数据,但是越简单越具有生命力,果断放弃。)。所以将0~6作为节点,每个骨牌就是一条边。
  所以就转换成了已知7个节点和n条边,要将每条边都走一边,很明显是个欧拉路径
PS: SGU的数据很变态的,数量大,考虑方面要周全。此题要考虑:是否联通图,是否存在欧拉路。

 
  
#include < stdio.h >
#include
< stdlib.h >
int head[ 7 ];
int buff[ 201 ];
int * side = & buff[ 100 ];
int buff2[ 201 ];
int * next = & buff2[ 100 ];
int len;
int count[ 7 ];
int used[ 101 ];

void add( int x, int y)
{
int i;
i
= ++ len;
side[i]
= y;
next[i]
= head[x];
head[x]
= i;

side[
- i] = x;
next[
- i] = head[y];
head[y]
= - i;

count[x]
++ , count[y] ++ ;
}
int ans[ 101 ];
int end;

void dfs( int k)
{
int i;
i
= head[k];
while (i != 0 ){
if ( ! used[abs(i)]){
used[abs(i)]
= 1 ;
dfs(side[i]);
ans[end
++ ] = i;
}
i
= next[i];
}
}

int main( int argc, char ** argv)
{
int i;
int a, b;
int n, t, s;
scanf(
" %d " , & n);
for (i = 0 ; i < n; i ++ ){
scanf(
" %d%d " , & a, & b);
add(a, b);
}
t
= 0 ;
for (i = 0 ; i <= 6 ; i ++ ){
if (count[i] & 1 ){
t
++ ;
s
= i;
}
}
if (t > 2 ){
printf(
" No solution\n " );
exit(
0 );
}
if (t == 0 ){
for (i = 0 ; i <= 6 ; i ++ ){
if (count[i] > 0 ){
s
= i;
break ;
}
}
}
dfs(s);
for (i = 1 ; i <= n; i ++ ){
if ( ! used[i]){
printf(
" No solution\n " );
exit(
0 );
}
}
for (i = end - 1 ; i >= 0 ; i -- ){
if (ans[i] > 0 ){
printf(
" %d +\n " , ans[i]);
}
else {
printf(
" %d -\n " , - ans[i]);
}
}
return 0 ;
}

转载于:https://www.cnblogs.com/yylogo/archive/2011/06/04/SGU-101.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值