sgu101

来源:互联网 发布:流放之路腾讯优化差 编辑:程序博客网 时间:2024/06/06 14:23

SGU101 Domino

题目大意:

描述

多米诺骨牌,一种用小的方的木块或其他材料,每个都被一些点在面上标记,这些木块通常被称为骨牌。每个骨牌的面都被一条线分成两个方形,两边各有一定点数。

N个多米诺骨牌,每个骨牌左右两侧分别有一个0~6的整数(骨牌可以旋转以调换其左右两数),求一种把这些骨牌从左到右排列的方案,使得所有相邻的两数字相等(即左边骨牌右侧的数字等于右边骨牌左侧的数字)。

输入

第一行是一个整数N(1 ≤ N ≤ 100),表示骨牌的数量。接下来的N行描述每块骨牌,每块左右两边有不同的点数。

输出

如果无法安排,输出“No solution”。如果可能,输出任何一种,每行有一个数字,和“+”或“-”,前者代表不旋转,后者代表旋转。

样例输入

5

1 2

2 4

2 4

6 4

2 1

样例输出

2 -

5 +

1 +

3 +

4 -

 

暴力的DFS会超时(这是不用解释的)

显然使用的是欧拉路径求解。

若不知道欧拉路径,请自行百度(一笔画问题)(提供参考http://blog.csdn.net/prime_min/article/details/40686563)

 

具体想法:1.建立欧拉路径图。

2.根据每个点的性质判断是否有解(若奇点个数为0或2,则有解,否则无解)

若有解:

3.奇点个数为0,则从任意一个存在的点开始遍历整个图。

4.奇点个数为2,则从奇点开始遍历整个图。

5.若遍历成功,则记录路径,按题目要求输出。

   若遍历不成功,则无解。

 

注意事项:

1.看清楚到底哪一面是正面,哪一面是负面。

2.奇点个数为0时,要从一个存在的点开始(不存在的点不能遍历,原因自行脑补)。

3.值得注意的一点,在输出时一张domino牌只能用一次,如果搞错会在test 5之前Wrong Answer

 

下面附上我的代码:

#include <stdio.h>#include <stdlib.h>#include <math.h>struct d{  int up;  int down;}domino[101],ans[101];int oula[7][7];int point[7];int start,num,n;int check[101];int total,pass;void search(int i)   //遍历整个欧拉路径{  int j;  for (j=0;j<=6;j++)    if (oula[i][j])      {     oula[i][j]--;     oula[j][i]--;     search(j);     ans[++total].up=i;     ans[total].down=j;      }  return ;}void init(){  int i,j,k;  scanf("%d",&n);  for (i=1;i<=n;i++)   //输入和构建欧拉图    {    scanf("%d%d",&domino[i].up,&domino[i].down);    oula[domino[i].up][domino[i].down]++;    oula[domino[i].down][domino[i].up]++;    point[domino[i].up]++;    point[domino[i].down]++;    }  for (i=6;i>=0;i--)  //寻找奇点和个数    if (point[i]&1)      { num++; start=i; }  if (num==0) //若奇点个数为0,找第一个存在的点作为起始点    for (;start<7 && point[start]==0;start++);  if (num!=2 && num!=0)  //根据奇点个数判断是否有解    {    printf("No solution");    return ;}  else    {    search(start);    if (total<n)  //根据便利状况判断是否有解      {      printf("No solution");      return ;  }    for (i=1;i<=total;i++)  //根据路径输出答案      for (j=1;j<=n;j++)        if (!check[j])          if (domino[j].up==ans[i].up && domino[j].down==ans[i].down)            {            check[j]=1;    printf("%d -\n",j);    break;            }          else if (domino[j].up==ans[i].down && domino[j].down==ans[i].up)            {check[j]=1;printf("%d +\n",j);break;}    }  return ;}int main(){  init();  return 0;}

0 0
原创粉丝点击