pku 1166 the clocks 解题报告
高斯消去法的典型应用
题意:
输入提供9个钟表的位置(钟表的位置只能是0点、3点、6点、9点,分别用0、1、2、3)表示。而题目又提供了9的步骤表示可以用来调正钟的位置,例如1 ABDE表示此步可以在第一、二、四、五个钟调正,如原来是0点,那么调正后为3点。问经过那些步骤可以导致9个钟的位置都在0点。
算法:
如果数学敏感度不强的话,那么此题很容易陷入bfs算法来做,时间复杂度就很大了。其实我们可以仔细观察题意的要求:
Move Affected clocks
1 ABDE
2 ABC
3 BCEF
4 ADG
5 BDEFH
6 CFI
7 DEGH
8 GHI
9 EFHI
影响第一个钟的就仅有1、2、4move了,同理其他也是这样,而在sample钟的第一个中只需要移动一步就可以达到0点,此时就发现了一个线性规律。我们可否将1、2、4move设置为x1,x2,x4呢?而且x1+x2+x4=1.问题看来变得很简单。我们现在尝试将所有与每个钟都相关的步骤联系起来,如下:
x1+x2+x4=1
x1+x2+x3+x5=1
x2+x3+x6=0
x1+x4+x5+x7=2
x1+x3+x5+x7+x9=2
x3+x5+x6+x9=2
x4+x7+x8=2
x5+x7+x8+x9=3
x6+x8+x9=2
与output结果相比,很容易联想到x4=1,x5=1,x7=1,x8=1,其他x值都为0.经过检查,与猜想符合。那么问题就是编写高斯消去法的问题了。
AC代码:
#include<iostream>
using namespace std;
int move[9][9] = {
{1, 1, 0, 1, 1, 0, 0, 0, 0},
{1, 1, 1, 0, 0, 0, 0, 0, 0},
{0, 1, 1, 0, 1, 1, 0, 0, 0},
{1, 0, 0, 1, 0, 0, 1, 0, 0},
{0, 1, 0, 1, 1, 1, 0, 1, 0},
{0, 0, 1, 0, 0, 1, 0, 0, 1},
{0, 0, 0, 1, 1, 0, 1, 1, 0},
{0, 0, 0, 0, 0, 0, 1, 1, 1},
{0, 0, 0, 0, 1, 1, 0, 1, 1}
};
int N = 9;
int f[9][9];
int ans[9], x[9];
int Guass()
{
int i, j, k, temp;
bool flag;
for (i = 0; i <= N - 1; i++)
{
if (f[i][i] == 0)
{
flag = false;
for (j = i + 1; j <= N - 1; j++)
{
if (f[j][i] != 0)
{
flag = true;
for (k = 0; k <= N - 1; k++)
{
temp = f[i][k];
f[i][k] = f[j][k];
f[j][k] = temp;
}
temp = ans[i];
ans[i] = ans[j];
ans[j] = temp;
break;
}
}
if (!flag)
{
return 1;
}
}
for (j = i + 1; j <= N - 1; j++)
{
if (f[j][i] != 0)
{
temp = f[j][i];
for (k = i; k <= N - 1; k++)
{
f[j][k] *= f[i][i];
f[j][k] -= (f[i][k] * temp);
}
ans[j] = ans[j] * f[i][i] - ans[i] * temp;
}
}
}
for (i = N - 1; i >= 0; i--)
{
temp = ans[i];
for (j = N - 1; j > i; j--)
{
temp -= f[i][j] * x[j];
}
temp = (temp % 4 + 4) % 4;
for (j = 0; j <= 3; j++)
{
if ((j * f[i][i] % 4 + 4) % 4 == temp)
{
x[i] = j;
}
}
}
return 0;
}
int main()
{
freopen("1.txt", "r", stdin);
int i, j;
int clocks[9];
for (i = 0; i < N; i++)
{
cin >> clocks[i];
}
for (i = 0; i < N; i++)
{
for (j = 0; j < N; j++)
{
f[i][j] = move[j][i];
}
ans[i] = (4 - clocks[i]) % 4;
}
Guass();
for (i = 0; i < N; i++)
{
x[i] = (x[i] % 4 + 4) % 4;
}
for (i = 0; i < N; i++)
{
for (j = 1; j <= x[i]; j++)
{
cout << i + 1 << " ";
}
}
cout << endl;
return 0;
}