这道题目和1830比较类似,1830是求解的个数,这道题目相当于求线性方程组的整数解(注意,这道题目的陷阱之一就是解出来的结果可能不是整数,反正我的代码一开始就是有的是小数)
题目主要内容:有9个钟,其中9个操作方法来扳动上面的指针,每个操作每次只能把指针移动90度,且每个操作是对一组钟进行操作(即执行每个操作之后有几个钟的状态被改变了90度而不是单独某个钟的状态改变了90度)。操作与其影响的钟的对应表如表一所示:
表一
题目要求的是给出这9个钟的初始状态(0表示指向12点,1表示指向3点,2表示指向6点,3表示指向6点)用操作1-9采用最少的移动次数操作这些钟,使它们都指向12点。
思路:根据操作与钟表的关系我们可以构造一个关系矩阵,如表二所示
行表示钟,列表示操作,例如,操作1,2,4被采用之后A都会受到影响,移动一步(即90度)。所以题目的意思就是求操作1-9都被操作了多少次,使得每个钟表从初始状态被调整到12点的那个状态,即每个钟表的状态变化=操作1*操作次数+操作2*操作次数+…+操作9*操作次数。
用测试数据作为例子说明一下:
但是注意,1-9操作的次数并不是这道题目的输出结果,它要求咱们把每个操作的过程输出来,也就是如果我操作了2次9号操作那么就输出9 9。还是看测试数据,虽然求出来的结果是
但是输出的结果是4,5,8 ,9
(这里之前卡了一下,一开始我以为操作出现的顺序会影响钟表的状态,但是仔细想一下发现操作的出现次序与钟表的最后状态没关系,即操作顺序 1 3 1与操作1 1 3是一样的,若有疑问可以自己模拟操作一下。所以只需要求出每个操作的操作次数,从小到大把次数对应的操作序号输出就可以了。)
陷阱1:求解出线性方程组的解的时候,有的时候出现非整数解的情况,这说明按这个数移动是最小的移动数,但是操作不了,那我们只能不断地再状态变化上面再加上一轮(即4)使得求得的数是整数。
陷阱2:求解出的解释负数,即往负方向转能更快到达12点的状态,但是题目里没有说可以用负方向转的,所以只能在其上面不断的加上一轮使得移动的次数变成正数。
代码:
#include<iostream>
#include<cmath>
using namespace std;
int a[9][9]={{1,1,0,1,0,0,0,0,0},
{1,1,1,0,1,0,0,0,0},
{0,1,1,0,0,1,0,0,0},
{1,0,0,1,1,0,1,0,0},
{1,0,1,0,1,0,1,0,1},
{0,0,1,0,1,1,0,0,1},
{0,0,0,1,0,0,1,1,0},
{0,0,0,0,1,0,1,1,1},
{0,0,0,0,0,1,0,1,1}};
float b[9][10];
void convert(int n,int m)
{
int i,j,t,swapline,tag,time;
float mul,cal[10];
for(i=0;i<n;i++)
{
//找到不为0的那行;
for(j=i;j<n;j++)
{
if(b[j][i]!=0)
break;
}
//若当前要处理的行的位置等于0,那么把不等于0的与它交换
if(j<n)
{
if(j!=i)
{
swapline=j;
for(j=i;j<m;j++)
{
t=b[swapline][j];
b[swapline][j]=b[i][j];
b[i][j]=t;
}
}
//将子矩阵处理成第一列为0 的
for(j=i+1;j<n;j++)
{
tag=0;
if(b[j][i]!=0)
{
mul=-b[i][i]/b[j][i];
for(t=i;t<m;t++)
{
b[j][t]=mul*b[j][t]+b[i][t];
}
}
}
}
}
for(j=0;j<n;j++)
{
tag=0;
for(t=j;t<m;t++)
{
if((int)b[j][t]!=b[j][t])
tag=1;
}
if(tag)
{
time=2;
while(tag)
{
tag=0;
for(t=j;t<m;t++)
{
cal[t]=b[j][t]*time;
if((int)cal[t]!=cal[t])
tag=1;
}
time++;
}
for(t=j;t<m;t++)
b[j][t]=cal[t];
}
}
}
int main()
{
int s[9];
float result[9],sum,rl,right;
int i,j,t,time,tp;
for(i=0;i<9;i++)
for(j=0;j<9;j++)
b[i][j]=a[i][j];
for(i=0;i<9;i++)
{
scanf("%d",&t);
s[i]=(4-t)%4;
b[i][9]=s[i];
}
convert(9,10);
for(i=8;i>=0;i--)
{
sum=0;
for(j=8;j>i;j--)
{
sum+=result[j]*b[i][j];
}
time=0;
rl=0.1;
while((int)rl!=rl)
{
right=b[i][9]-sum+4*time;
rl=right/(b[i][i]);
time++;
}
time=1;
while(rl<0)
{
rl+=time*4;
}
result[i]=(int)rl%4;
}
for(i=0;i<9;i++)
{
if(result[i]>0)
{
for(j=0;j<result[i];j++)
printf("%d ",i+1);
}
}
return 0;
}