拨钟问题

如题使用枚举的方式,但有些可能可以通过一定条件否决掉从而减少判断次数

拨钟问题

来源: POJ

注意: 总时间限制: 1000ms 内存限制: 65536kB

描述

有9个时钟,排成一个3*3的矩阵。

        |-------|    |-------|    |-------|
        |       |    |       |    |   |   |
        |---O   |    |---O   |    |   O   |
        |       |    |       |    |       |
        |-------|    |-------|    |-------|    
            A            B            C    
        |-------|    |-------|    |-------|
        |       |    |       |    |       |
        |   O   |    |   O   |    |   O   |
        |   |   |    |   |   |    |   |   |
        |-------|    |-------|    |-------|    
            D            E            F    
        |-------|    |-------|    |-------|
        |       |    |       |    |       |
        |   O   |    |   O---|    |   O   |
        |   |   |    |       |    |   |   |
        |-------|    |-------|    |-------|    
            G            H            I    
                       (图 1)

现在需要用最少的移动,将9个时钟的指针都拨到12点的位置。共允许有9种不同的移动。如下表所示,每个移动会将若干个时钟的指针沿顺时针方向拨动90度。

移动    影响的时钟  1        ABDE 
 2        ABC 
 3        BCEF 
 4        ADG 
 5        BDEFH 
 6        CFI 
 7        DEGH 
 8        GHI 
 9        EFHI         
    (图 2)

输入

从标准输入设备读入9个整数,表示各时钟指针的起始位置。0=12点、1=3点、2=6点、3=9点。

输出

输出一个最短的移动序列,使得9个时钟的指针都指向12点。按照移动的序号大小,输出结果。

样例输入

3 3 0
2 2 2
2 1 2

样例输出

4 5 8 9

</pre><pre name="code" class="cpp">#include <stdio.h>
int site[10];    //site[1]-site[9]对应9个钟的状态
                   //A B C D E F G H I
//const int move1[]={1,1,0,1,1,0,0,0,0};   //i1 
//const int move2[]={1,1,1,0,0,0,0,0,0};   //i2
//const int move3[]={0,1,1,0,1,1,0,0,0};   //i3
//const int move4[]={1,0,0,1,0,0,1,0,0};   //i4
//const int move5[]={0,1,0,1,1,1,0,1,0};   //i5
//const int move6[]={0,0,1,0,0,1,0,0,1};   //i6
//const int move7[]={0,0,0,1,1,0,1,1,0};   //i7
//const int move8[]={0,0,0,0,0,0,1,1,1};   //i8
//const int move9[]={0,0,0,0,1,1,0,1,1};   //i9
//A  1 2 4      钟A只能被i1、i2、i4三个拨动改变,所以当钟A不为0时,显然1、2、4不能同时为0,以此判断跳过一些不必要的枚举
//B	 1 2 3 5
//C  2 3 6
//D  1 4 5 7
//E  1 3 5 7 9
//F  3 5 6 9
//G  4 7 8
//H  5 7 8 9
//I  6 8 9
int main(void){
	char tmp;                  
	int i1,i2,i3,i4,i5,i6,i7,i8,i9;
	int station[10]={0};
	int sum=50;
	site[0]=0;
	for(int m=0;m<3;m++){
		for(int n=0;n<3;n++)
			//scanf_s("%d",&site[3*m+n+1],1);
		//scanf_s("%c",&tmp,1);
		scanf("%d",&site[3*m+n+1]);
		scanf("%c",&tmp);
	}
	for(i1=0;i1<4;i1++){
		for(i2=0;i2<4;i2++)
			for(i3=0;i3<4;i3++)
				for(i4=0;i4<4;i4++){
					if(site[1]!=0 && i1==0 && i2==0 && i4==0)    //A
							continue;
					for(i5=0;i5<4;i5++){
						if(site[2]!=0 && i1==0 && i2==0 && i3==0 && i5==0)//B
							continue;
						for(i6=0;i6<4;i6++){
							if(site[3]!=0 && i2==0 && i3==0 && i6==0)//C
								continue;
							for(i7=0;i7<4;i7++){
								if(site[4]!=0 && i1==0 && i4==0 && i5==0 && i7==0)//D
									continue;
								for(i8=0;i8<4;i8++){
									if(site[7]!=0 &&i4==0 && i7==0 && i8==0)//G
										continue;
									for(i9=0;i9<4;i9++){
										if(site[5]!=0 &&i1==0 && i3==0 && i5==0 && i7==0 && i9==0)//E
											continue;
										if(site[6]!=0 && i3==0 && i5==0 && i6==0 && i9==0)//F
											continue;
										if(site[8]!=0 && i5==0 && i7==0 && i8==0 && i9==0)//H
											continue;
										if(site[9]!=0 && i6==0 && i8==0 && i9==0)//I
											continue;
										if((0==(site[1]+i1+i2+i4)%4) && (0==(site[2]+i1+i2+i3+i5)%4) && (0==(site[3]+i2+i3+i6)%4)
											&& (0==(site[4]+i1+i4+i5+i7)%4) && (0==(site[5]+i1+i3+i5+i7+i9)%4) && (0==(site[6]+i3+i5+i6+i9)%4)
											&& (0==(site[7]+i4+i7+i8)%4) && (0==(site[8]+i5+i7+i8+i9)%4) && (0==(site[9]+i6+i8+i9)%4)){ 
												//printf("%d,%d,%d,%d,%d,%d,%d,%d,%d",i1,i2,i3,i4,i5,i6,i7,i8,i9);
											//printf("\n");
												if(sum>i1+i2+i3+i4+i5+i6+i7+i8+i9){
													sum=i1+i2+i3+i4+i5+i6+i7+i8+i9;
													station[1]=i1;
													station[2]=i2;
													station[3]=i3;
													station[4]=i4;
													station[5]=i5;
													station[6]=i6;
													station[7]=i7;
													station[8]=i8;
													station[9]=i9;
												}
										}
									}
								}
							}
						}

					}
				}		
	}
	if(sum!=50)
		for(int m=1;m<10;m++){
			while(station[m]!=0){
				printf("%d ",m);
				station[m]--;
			}
		}
		printf("\n");
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值