算法丑陋,时间略长,还望指教。
#include <stdio.h>
#include <stdlib.h>
/*
首先,我们考虑用长度为9的数组表示表盘的状态以及调表的操作,终止的条件是表盘状态数组所有元素模4为0;
如果一种操作使用超过4次,那么相当于没有操作,所以操作数组需要多出一位记录造作使用的次数,一个操作最多使用3次
特别是我们注意到这个题没有问操作的顺序,所以操作的前后顺序其实是没有影响的;
这样其实是对进行了哪些操作,操作了多少次进行枚举,也就是对一个9*4的矩阵进行枚举;并求矩阵行元素和的最小值,
一共枚举4的9次方次
*/
short clocks[9],min=1000,operations[9][9],count[9],best[9];
void change()//这个函数的作用是按照count调整clocks,并修改min,再把clocks改回去
{
short i,j,flag=1,n=0;
for(i=0;i<9;i++)
n+=count[i];
if(n>=min) return;
for(i=0;i<9;i++)
for(j=0;j<9;j++)
clocks[j]+=(operations[i][j]*count[i]);
for(i=0;i<9;i++)
{
if((clocks[i]%4)!=0)
flag=0;
}
if(flag)
{
min=n;
for(i=0;i<9;i++)
best[i]=count[i];
}
for(i=0;i<9;i++)
for(j=0;j<9;j++)
clocks[j]-=(operations[i][j]*count[i]);
}
int main()
{
operations[0][0]=operations[0][1]=operations[0][3]=operations[0][4]=1;
operations[1][0]=operations[1][1]=operations[1][2]=1;
operations[2][1]=operations[2][2]=operations[2][4]=operations[2][5]=1;
operations[3][0]=operations[3][3]=operations[3][6]=1;
operations[4][1]=operations[4][3]=operations[4][4]=operations[4][5]=operations[4][7]=1;
operations[5][2]=operations[5][5]=operations[5][8]=1;
operations[6][3]=operations[6][4]=operations[6][6]=operations[6][7]=1;
operations[7][6]=operations[7][7]=operations[7][8]=1;
operations[8][4]=operations[8][5]=operations[8][7]=operations[8][8]=1;
short i,j;
for(i=0;i<9;i++)
scanf("%d",&clocks[i]);
while(count[0]<4)
{
change();
count[8]++;
for(i=8;i>0;i--)
{
count[i-1]+=(count[i]/4);
count[i]=count[i]%4;
}
}
for(i=0;i<9;i++)
for(j=0;j<best[i];j++)
printf("%d ",i+1);
return 0;
}