现在的位置: 首页 > 综合 > 正文

USACO SECTION 1.4 The Clocks

2017年11月23日 ⁄ 综合 ⁄ 共 5903字 ⁄ 字号 评论关闭
文章目录

The Clocks
IOI'94 - Day 2

Consider nine clocks arranged in a 3x3 array thusly:

|-------|    |-------|    |-------|    
|       |    |       |    |   |   |    
|---O   |    |---O   |    |   O   |          
|       |    |       |    |       |           
|-------|    |-------|    |-------|    
    A            B            C

|-------|    |-------|    |-------|
|       |    |       |    |       |
|   O   |    |   O   |    |   O   |
|   |   |    |   |   |    |   |   |
|-------|    |-------|    |-------|
    D            E            F

|-------|    |-------|    |-------|
|       |    |       |    |       |
|   O   |    |   O---|    |   O   |
|   |   |    |       |    |   |   |
|-------|    |-------|    |-------|
    G            H            I

The goal is to find a minimal sequence of moves to return all the dials to 12 o'clock. Nine different ways to turn the dials on the clocks are supplied via a table below; each way is called a move. Select for each move a number 1 through 9 which will cause
the dials of the affected clocks (see next table) to be turned 90 degrees clockwise.

Move Affected clocks
1 ABDE
2 ABC
3 BCEF
4 ADG
5 BDEFH
6 CFI
7 DEGH
8 GHI
9 EFHI


Example

Each number represents a time accoring to following table:

9 9 12       9 12 12       9 12 12        12 12 12      12 12 12 
6 6 6  5 ->  9  9  9  8->  9  9  9  4 ->  12  9  9  9-> 12 12 12 
6 3 6        6  6  6       9  9  9        12  9  9      12 12 12 

[But this might or might not be the `correct' answer; see below.]

PROGRAM NAME: clocks

INPUT FORMAT

Lines 1-3: Three lines of three space-separated numbers; each number represents the start time of one clock, 3, 6, 9, or 12. The ordering of the numbers corresponds to the first example above.

SAMPLE INPUT (file clocks.in)

9 9 12
6 6 6
6 3 6

OUTPUT FORMAT

A single line that contains a space separated list of the shortest sequence of moves (designated by numbers) which returns all the clocks to 12:00. If there is more than one solution, print the one which gives the lowest number when the moves are concatenated
(e.g., 5 2 4 6 < 9 3 1 1).

SAMPLE OUTPUT (file clocks.out)

4 5 8 9
/*
ID: conicoc1
LANG: C
TASK: clocks
*/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

#define A 0
#define B 1
#define C 2
#define D 3
#define E 4
#define F 5
#define G 6
#define H 7
#define I 8

void Move1(int *Clocks)
{
	Clocks[A]+=3;
	Clocks[B]+=3;
	Clocks[D]+=3;
	Clocks[E]+=3;	
	
}

void Move2(int *Clocks)
{
	Clocks[A]+=3;
	Clocks[B]+=3;
	Clocks[C]+=3;
	
}

void Move3(int *Clocks)
{
	Clocks[B]+=3;
	Clocks[C]+=3;
	Clocks[E]+=3;
	Clocks[F]+=3;	
	
}

void Move4(int *Clocks)
{
	Clocks[A]+=3;
	Clocks[D]+=3;
	Clocks[G]+=3;
	
}

void Move5(int *Clocks)
{
	Clocks[B]+=3;
	Clocks[D]+=3;
	Clocks[E]+=3;
	Clocks[F]+=3;	
	Clocks[H]+=3;
	
}

void Move6(int *Clocks)
{
	Clocks[C]+=3;
	Clocks[F]+=3;
	Clocks[I]+=3;
		
}

void Move7(int *Clocks)
{
	Clocks[D]+=3;
	Clocks[E]+=3;
	Clocks[G]+=3;
	Clocks[H]+=3;	
	
}

void Move8(int *Clocks)
{
	Clocks[G]+=3;
	Clocks[H]+=3;
	Clocks[I]+=3;
	
}

void Move9(int *Clocks)
{
	Clocks[E]+=3;
	Clocks[F]+=3;
	Clocks[H]+=3;
	Clocks[I]+=3;
	
}

int IsFinished(int *Clocks)
{
	int i;
	for(i=0;i<9;i++)
		if(Clocks[i]%12!=0)
			return 0;
	return 1;
}

void swap(int *a,int *b)
{
	int i;
	for(i=0;i<9;i++)
		a[i]=b[i];
}


int main()
{
	FILE *fin,*fout;
	fin=fopen("clocks.in","r");
	fout=fopen("clocks.out","w");
	
	int Clocks[9],temp[9];
	int M[9],P[9]={0},Sum=28;  //记录每种移动方式的次数 
	int i,j,k,t;
	
	for(i=0;i<9;i++)
	{
		fscanf(fin,"%d",&Clocks[i]);
	}
	swap(temp,Clocks);
	
	for(M[0]=0;M[0]<=3;M[0]++)
	{
		for(M[1]=0;M[1]<=3;M[1]++)
		{
			for(M[2]=0;M[2]<=3;M[2]++)
			{
				for(M[3]=0;M[3]<=3;M[3]++)
				{
					for(M[4]=0;M[4]<=3;M[4]++)
					{
						for(M[5]=0;M[5]<=3;M[5]++)
						{
							for(M[6]=0;M[6]<=3;M[6]++)
							{
								for(M[7]=0;M[7]<=3;M[7]++)
								{
									for(M[8]=0;M[8]<=3;M[8]++)
									{
										for(i=0;i<9;i++)
										{
											for(j=0;j<M[i];j++)
											switch(i)
											{
												case 0:Move1(Clocks);break;
												case 1:Move2(Clocks);break;
												case 2:Move3(Clocks);break;
												case 3:Move4(Clocks);break;
												case 4:Move5(Clocks);break;
												case 5:Move6(Clocks);break;
												case 6:Move7(Clocks);break;
												case 7:Move8(Clocks);break;
												case 8:Move9(Clocks);break;
											}
										}
										if(IsFinished(Clocks))
										{
											if(Sum>M[0]+M[1]+M[2]+M[3]+M[4]+M[5]+M[6]+M[7]+M[8])
											{
												for(k=0;k<9;k++)
												{
													P[k]=M[k];
												}
												Sum=M[0]+M[1]+M[2]+M[3]+M[4]+M[5]+M[6]+M[7]+M[8];
											}
									//		getchar();
										}

										swap(Clocks,temp);
									}
								}
							}
						}
					}
				}			
			}
		}
	}
	k=0;
	t=0;
	for(i=0;i<9;i++)
	{
		for(j=0;j<P[i];j++)
		{
			k++;
		}
	}	
	for(i=0;i<9;i++)
	{
		for(j=0;j<P[i];j++)
		{
			fprintf(fout,"%d",i+1);
			t++;
			if(t!=k)
				fprintf(fout," ");
		}
	}	
	fprintf(fout,"\n");
	
	return 0;
}

虐啊。。太虐了。。做到1.4就开始虐了。。。

让我回想一下我开始的各种想法。。

 

一开始以为选择移动的9种方式是有优先权的。。。不停的再想优先权,想了半天不对。

后来模拟了一下已知的过程,对于给定的9个钟,方法的顺序可以不一样,所以就有了那个坑爹的解九元一次方程组,还专门复习了一下矩阵的高斯消元,

折腾了半天发现等式右边是4n-1或2或3,是不定的,思考无果。放弃

 

最后实在没办法了,就只好用暴力了

对于每种方法最多只能执行3次,因为4次就等于没有动,所以开辟了一个数组存放每种方法的执行次数。

本打算一旦找到符合的,就弹出循环,后来样例3检测的时候出错了,发现需要比较所有可能的情况,选数组和最低的情况。

 

另外最后所要求的输出方法,每个数字之间有空格,最后和开头没有空格,对于整体输出想了半天没有什么好的方法,结果码了一大串。。。

 

去NOCOW上面研究一下BFS和DFS的方法。对于深搜和广搜的理解还是不够深刻啊啊。

 

/*
ID: conicoc1
LANG: C
TASK: barn1
*/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

int Stack[3000000];
int Queue[3000000];
int Flag[3000000];
int road[3000000][2];
int top=0,front=0,rear=0;
int clock[9];
int temp[9];

void act(int p)
{
    int i,j,k;
    if(p==1)
    {
        clock[0]=(clock[0]+1)%4;
        clock[1]=(clock[1]+1)%4;
        clock[3]=(clock[3]+1)%4;
        clock[4]=(clock[4]+1)%4;
    }
    if(p==2)
    {
        clock[0]=(clock[0]+1)%4;
        clock[1]=(clock[1]+1)%4;
        clock[2]=(clock[2]+1)%4;
    }
    if(p==3)
    {
        clock[2]=(clock[2]+1)%4;
        clock[1]=(clock[1]+1)%4;
        clock[5]=(clock[5]+1)%4;
        clock[4]=(clock[4]+1)%4;
    }
    if(p==4)
    {
        clock[0]=(clock[0]+1)%4;
        clock[3]=(clock[3]+1)%4;
        clock[6]=(clock[6]+1)%4;
    }
    if(p==5)
    {
        clock[5]=(clock[5]+1)%4;
        clock[1]=(clock[1]+1)%4;
        clock[3]=(clock[3]+1)%4;
        clock[4]=(clock[4]+1)%4;
        clock[7]=(clock[7]+1)%4;
    }
    if(p==6)
    {
        clock[2]=(clock[2]+1)%4;
        clock[5]=(clock[5]+1)%4;
        clock[8]=(clock[8]+1)%4;
    }
    if(p==7)
    {
        clock[6]=(clock[6]+1)%4;
        clock[7]=(clock[7]+1)%4;
        clock[3]=(clock[3]+1)%4;
        clock[4]=(clock[4]+1)%4;
    }
    if(p==8)
    {
        clock[6]=(clock[6]+1)%4;
        clock[7]=(clock[7]+1)%4;
        clock[8]=(clock[8]+1)%4;
    }
    if(p==9)
    {
        clock[8]=(clock[8]+1)%4;
        clock[7]=(clock[7]+1)%4;
        clock[5]=(clock[5]+1)%4;
        clock[4]=(clock[4]+1)%4;
    }
}

int invert()
{
	int i,sum=0;
	int n=1;
	for(i=0;i<9;i++)
	{
		sum+=clock[i]*n;
		n*=4;	
	}
	return sum;
}

void revert(int sum)
{
	int i;
	for(i=0;i<9;i++)
	{
		clock[i]=sum%4;
		sum/=4;
	}
}

void InStack(int s)
{
	if(s==Queue[0])
	{
		return;
	}
//	printf("%d %d\n",s,road[s][0]);
	InStack(road[s][0]);
	Stack[top++]=road[s][1];   //最下面是根	
}
int main()
{
	FILE *fin,*fout,*ftxt;
	fin=fopen("clocks.in","r");
	fout=fopen("clocks.out","w");
	
    memset(Flag,-1,sizeof(Flag));
    memset(road,-1,sizeof(road));

	int i,j,k;
	for(i=0;i<9;i++)
	{
		fscanf(fin,"%d",&clock[i]);
		clock[i]=(clock[i]/3)%4;
	}
	
	int s,t;  //保存转换的状态
	
	s=invert();
	Queue[rear++]=s;  //将该状态进队
	printf("rear:%d,s:%d,Queue[0]:%d",rear,s,Queue[0]);
	Flag[s]=1;
	
	while(front!=rear)
	{
		s=Queue[front++];
		revert(s);
		for(j=0;j<9;j++)
			temp[j]=clock[j];
		for(i=1;i<=9;i++)
		{
			act(i);
			t=invert();
		//	printf("%d\n",t);
			if(t==0)
				getchar();
			if(Flag[t]==-1)
			{
				Flag[t]=1;
				Queue[rear++]=t;
				road[t][0]=s;
				road[t][1]=i;
			}
			for(j=0;j<9;j++)
				clock[j]=temp[j];
		}
		if(Flag[0]==1)
			break;
	} 
    		//			for(j=0;j<9;j++)
			//		printf("%d",clock[j]);		
	//接下来将路径递归进栈 
	InStack(0);


	for(i=0;i<top;i++)
		printf("%d ",Stack[i]);	
}

 

这个方法对我这个菜鸟来说感觉很有应用价值啊

抱歉!评论已关闭.