SGU 101 Domino

来源:互联网 发布:中科大mba知乎 编辑:程序博客网 时间:2024/04/30 19:41

题目地址:

http://acm.sgu.ru/problem.php?contest=0&problem=101

题目描述:

101. Domino

time limit per test: 0.25 sec. 
memory limit per test: 4096 KB

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.

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.

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).

Sample Input

51 22 42 46 42 1

Sample Output

2 -5 +1 +3 +4 -

题意:

找一条连通的欧拉路径。

题解:

实际上就是,找一条连通的欧拉路(注意不是欧拉回路)。
代码写的略乱,好久没写了。其大体剪枝有:
1、首先度为奇数的节点数量肯定要<=2,不然不可能连通
2、度为奇数的节点一定在欧拉路的两端,不可能在中间。不然一样不可能连通,自己画几个实例看看就知道。但并不是在两端的节点就一定要是奇数度的节点(欧拉回路的“形式”也可以当做一个特殊欧拉路,即所有节点的度都是偶数)
3、两边度的数的数量是1的节点,不可能连成欧拉路,这是一个孤立点,比如,节点 (2,3)其他的节点根本没有出现2和3的度,所以这个节点肯定是孤立的。
其大体算法如下:
1、首选选择一个奇数度作为起点,如果不存在奇数度,就任选一个偶数度节点作为起点。
2、深搜DFS,按照规则连接其他节点。
3、如果能连通则结束总DFS,如果不能连通 也结束总DFS(注意,这是我超时原因,也即无论起点选择哪个节点,只要走不通那换其他节点作为起点也肯定走不通,自己画实例看)
代码:
#include <stdio.h>#include <string.h>typedef struct dom{int ind;int l;int r;bool is_ro;}dom,* dom_link;dom dominos[105];dom queue_dom[105];bool visit_dominos[105]={false};int num_cnt[7];//record the left and right number's countint M=0;//the length of queue_domint N=0;//the length of dominos//dfs the dominosint dfs_dom(int cur){if(cur>N-1){return(1);}for(int i=0;i<=N-1;i++){if(!visit_dominos[i]){if(cur>0){if(queue_dom[cur-1].r==dominos[i].l){visit_dominos[i]=true;queue_dom[cur]=dominos[i];int flag=dfs_dom(cur+1);if(flag!=0) return(1);visit_dominos[i]=false;}else if(queue_dom[cur-1].r==dominos[i].r){visit_dominos[i]=true;queue_dom[cur]=dominos[i];int tmp=queue_dom[cur].l;queue_dom[cur].l=queue_dom[cur].r;queue_dom[cur].r=tmp;queue_dom[cur].is_ro=true;int flag=dfs_dom(cur+1);if(flag!=0) return(1);visit_dominos[i]=false;}}else{int left_flag=0;int right_flag=0;for(int j=0;j<=N-1;j++){if(num_cnt[dominos[j].l]%2!=0){visit_dominos[j]=true;queue_dom[cur]=dominos[j];int flag=dfs_dom(cur+1);if(flag!=0) return(1);visit_dominos[j]=false;left_flag=1;break;}if(num_cnt[dominos[j].r]%2!=0){visit_dominos[j]=true;queue_dom[cur]=dominos[j];int tmp=queue_dom[cur].l;queue_dom[cur].l=queue_dom[cur].r;queue_dom[cur].r=tmp;queue_dom[cur].is_ro=true;int flag=dfs_dom(cur+1);if(flag!=0) return(1);visit_dominos[j]=false;right_flag=1;break;}}if(!left_flag&&!right_flag){visit_dominos[i]=true;queue_dom[cur]=dominos[i];int flag=dfs_dom(cur+1);if(flag!=0) return(1);else return(0);//visit_dominos[i]=false;}else{return(0);}}}}return(0);}//pre check the dominosint pre_check(){int odd_cnt=0;for(int i=0;i<=7-1;i++){if(num_cnt[i]%2!=0) odd_cnt++;}if(odd_cnt>2) return(0);else return(1);}//pre check the dominosint pre_check1(){for(int i=0;i<=N-1;i++){if(num_cnt[dominos[i].l]==1&&num_cnt[dominos[i].r]==1) return(0);}return(1);}//main processint main(){while(scanf("%d",&N)!=EOF){memset(num_cnt,0,sizeof(num_cnt));for(int i=0;i<=N-1;i++){scanf("%d%d",&dominos[i].l,&dominos[i].r);dominos[i].ind=i;dominos[i].is_ro=false;//record the countnum_cnt[dominos[i].l]++;num_cnt[dominos[i].r]++;}memset(visit_dominos,false,sizeof(visit_dominos));//initif(pre_check()&&pre_check1()&&dfs_dom(0)){//print queue_domfor(int i=0;i<=N-1;i++){if(queue_dom[i].is_ro) printf("%d -\n",queue_dom[i].ind + 1);else printf("%d +\n", queue_dom[i].ind + 1);}}else{printf("No solution\n");}}return(0);}






0 0
原创粉丝点击