/* 问题描述: 著名医生的药方 很久以前,有一个医术非常高明的医生,曾经医治好了很多怪病。 但是,他开出的药方的字迹却是十分难以辨认,只有他自己和他自己的药剂师 才能读懂他的药方。有时候甚至是两个不同的药方的同一种药都是难以辨认出的。 不过,这个医生开药方的时候,习惯有一个固定的标准模式。他有一个药材库,里面共有 n种药,出了这n种药,他不会使用任何其他的药,对于每一种药,都有一个关于他的后续药 的集合,只有这种药的后续药才能够直接出现在这种药的下一个位置。当然,任何一种药 都可能同时是几种药的后续药。 这个医生开出的药房是一个列表的形式。在他的一个药房中,一种药只可能出现一次。 更奇怪的是,当他开出一种药和他的后续药以后,这种药的其他后续药就不可能出现在这之后的 序列中。 后来,一些书法家和医生共同分析了这个医生的大量药方,写出了他的所有药的清单。这里我们 有n个整数1,2,...,n来依次表示他的n种药。同时,他们也分析出了每一种药的可能的后续的药单。 现在,有一个关于这个医生的药方,药方中写有p种药。可惜的是药方中有一些药并没有具体的辨别出。 那么请你写一个程序,帮忙辨别出药方中不确认的药。当然对于不确定的药,可能可以构造出多种不同的 药方,那么请你找出所有的情况。 输入格式: 输入文件doctor.in的第一行只有一个整数n(0<n<=500),表示所有的药的种数。 在接下来的n行中,每行都有若干个数(中间用空格隔开),第i行表示的第i种药的后续 药的集合。再接下来的一行,又有一个整数p,表示具体的一个药方的药的数目。继续下来的p行, 每行有一个整数,表示这个药方第i个药被鉴别出来时k;如果k是0,表示这个药还没有被鉴别出来。 输出格式: 输出文件doctor.out的第一行是一个整数m,表示总共可已构造出m种不同的药方。接下来的m行, 每行应该有p个数,具体输出每一种情况的药方,中间用一个空格格开。所有的m行的输出,必须按照整数排序 顺序输出,行首行末无空格。 输入输出样例: ========================================================================= 样例1: Sample Input Output for the input 5 2 2 4 5 2 3 5 4 1 3 4 3 5 1 5 2 3 1 2 4 4 0 3 0 0 ========================================================================= ========================================================================= 样例2: Sample Input Output for the input 1 1 1 1 1 0 ========================================================================= ========================================================================= 样例3: Sample Input Output for the input 10 12 3 4 7 4 8 6 5 2 1 5 6 4 8 6 10 2 2 4 6 10 4 8 6 10 3 1 8 9 9 5 6 7 4 2 6 9 5 6 10 3 5 7 10 9 8 6 10 2 4 9 9 8 6 10 3 1 4 6 7 9 10 2 6 7 4 5 8 10 2 6 7 9 2 3 5 10 3 6 7 9 5 10 5 6 7 4 0 10 5 6 7 9 0 6 0 0 ========================================================================= */ /* Notice:为了方便我是从控制台输入输出的 */ /* @author aa_niaofang 2011-4-14 23:43:25 */ #include <stdio.h> #include <stdlib.h> #define M 10 struct save { int *link; struct save *next; }; /*global variable*/ struct save *Global_save=NULL;/*用来存储可能的药方*/ int count=0;/*用来计数可能药方的个数*/ /*定义两个值: 一个是药方中本来就有的药方 另一个是已经成功选择了的药方 */ /*药方中本来就有的药方*/ int *exsit=NULL; /*对药方是否使用进行标志*/ int *used=NULL; void search(int **,int*,int k,int p,int n);/*主要查找函数*/ bool van(int k,int i,int**a);/*判断i是否是k的前序药方*/ bool subsequnce(int k,int i,int**a);/*判断i是否是k的后续药方*/ void main() { int n; int p; int i,j; printf("Input the total number kinds of the priscreptions!/n"); scanf("%d",&n); int **a=(int **)malloc(sizeof(int *)*n); for(i=0;i<n;i++) { a[i]=(int*)malloc(sizeof(int)*M); } printf("Input the priscreption!/n"); for(i=0;i<n;i++) { j=0; int c; while(1) { scanf("%d",&c); a[i][j++]=c; if(getchar()=='/n') break; } a[i][j]=0; } printf("Input the priscreption number which been choosed!/n"); scanf("%d",&p); int *b=(int *)malloc(sizeof(int)*p); exsit=(int *)malloc(sizeof(int)*n+1); used=(int *)malloc(sizeof(int)*n+1); for(i=0;i<n+1;i++) { exsit[i]=0; used[i]=0; } printf("Input the priscreption which been choosed!/n"); for(i=0;i<p;i++) { scanf("%d",&b[i]); if(b[i]) { exsit[b[i]]=1; } } j=0; struct save *s=NULL; search(a,b,j,p,n); /*输出*/ s=Global_save; printf("%d/n",count); for(i=0;i<count;i++) { for(j=0;j<p;j++) { printf("%d ",(s->link)[j]); } printf("/n"); s=s->next; } } void search(int **a,int *b,int k,int p,int n) { if(k+1>p) { count++; struct save *s=(struct save*)malloc(sizeof(struct save)); s->link=(int *)malloc(sizeof(int)*p); s->next=NULL; for(int i=0;i<p;i++) { (s->link)[i]=b[i]; } if(Global_save==NULL) { Global_save=s; } else { struct save *t=Global_save; while(t->next) { t=t->next; } t->next=s; } return; } /*If k is the last prescription*/ if(k+1==p) { if(k==0) { b[k]=a[0][0]; search(a,b,k+1,p,n); return; } if(exsit[b[k]]==0) { int k1=k-1; for(int x=0;x<M && a[b[k1]-1][x];x++) { int flag=0; for(int j=0;j<k1;j++) { if(subsequnce(b[j],a[b[k1]-1][x],a) || a[b[k1]-1][x]==b[j]) { flag=1; break; } } if(flag==0 && used[a[b[k1]-1][x]]==0) { b[k]=a[b[k1]-1][x]; used[b[k]]=1; search(a,b,k+1,p,n); used[b[k]]=0; if(exsit[b[k]]==0) b[k]=0; } } } return; } if(exsit[b[k]]==0) { if(k==0) { for(int i=0;i<n;i++) { int flag=0; for(int j=k+2;j<p;j++) { if(van(b[j],i+1,a)) { flag=1; break; } } if(flag==1) continue; if(b[k+1]==0 && used[i+1]==0) { b[k]=i+1; used[b[k]]=1; search(a,b,k+1,p,n); used[b[k]]=0; if(exsit[b[k]]==0) b[k]=0; } else { for(int j=0;j<M && a[i][j];j++) { if(a[i][j]==b[k+1] && used[i+1]==0) { b[k]=i+1; used[i+1]=1; search(a,b,k+1,p,n); used[b[k]]=0; if(exsit[b[k]]==0) b[k]=0; } } } } } else { int k1=b[k-1]; for(int i=0;i<M &&a[k1-1][i];i++) { int flag=0; for(int x=0;x<k;x++) { if(a[k1-1][i]==b[x]) { flag=1; break; } } if(k-2>=0 && flag==0) { for(int j=0;j<k-1;j++) if(subsequnce(b[j],a[k1-1][i],a)) { flag=1; break; } } for(int j=k+2;j<p && flag==0;j++) { if(van(b[j],a[k1-1][i],a)) { flag=1; break; } } if(flag==0) { if(b[k+1]==0 && used[a[k1-1][i]]==0) { b[k]=a[k1-1][i]; used[b[k]]=1; search(a,b,k+1,p,n); used[b[k]]=0; if(exsit[b[k]]==0) b[k]=0; } else { for(int x=0;x<M &&a[a[k1-1][i]-1][x];x++) { if(b[k+1]==a[a[k1-1][i]-1][x] && used[a[k1-1][i]]==0) { b[k]=a[k1-1][i]; used[b[k]]=1; search(a,b,k+1,p,n); used[b[k]]=0; if(exsit[b[k]]==0) b[k]=0; break; } } } } } } } else { if(used[b[k]]==0) { used[b[k]]=1; search(a,b,k+1,p,n); used[b[k]]=0; if(exsit[b[k]]==0) b[k]=0; } } } /* 查找i是否为k前驱 */ bool van(int k,int i,int **a) { if(i==0) return false; for(int j=0;j<M && a[i-1][j];j++) { if(a[i-1][j]==k) return true; } return false; } /* 查找i是否为k的后继 */ bool subsequnce(int k,int i,int **a) { if(i==0) return false; for(int j=0;j<M && a[k-1][j];j++) { if(a[k-1][j]==i) return true; } return false; }