The Clocks
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 16797 | Accepted: 6939 |
Description
|-------| |-------| |-------| | | | | | | | |---O | |---O | | O | | | | | | | |-------| |-------| |-------| A B C |-------| |-------| |-------| | | | | | | | O | | O | | O | | | | | | | | | | |-------| |-------| |-------| D E F |-------| |-------| |-------| | | | | | | | O | | O---| | O | | | | | | | | | |-------| |-------| |-------| G H I (Figure 1)
There are nine clocks in a 3*3 array (figure 1). The goal is to return all the dials to 12 o'clock with as few moves as possible. There are nine different allowed ways to turn the dials on the clocks. Each such way is called a move. Select for each move a number 1 to 9. That number will turn the dials 90' (degrees) clockwise on those clocks which are affected according to figure 2 below.
Move Affected clocks 1 ABDE 2 ABC 3 BCEF 4 ADG 5 BDEFH 6 CFI 7 DEGH 8 GHI 9 EFHI (Figure 2)
Input
Your program is to read from standard input. Nine numbers give the start positions of the dials. 0=12 o'clock, 1=3 o'clock, 2=6 o'clock, 3=9 o'clock.
Output
Your program is to write to standard output. Output a shortest sorted sequence of moves (numbers), which returns all the dials to 12 o'clock. You are convinced that the answer is unique.
Sample Input
3 3 0 2 2 2 2 1 2
Sample Output
4 5 8 9
设C为当前操作的时钟状态(取值0~3),Xi为执行movei的次数,ai为movei是否能操作当前时钟,能为1,不能为0。
可得方程:(C + a1*X1 + a2*X2 + ... + a9*X9)mod4 = 0
即 (a1*X1 + a2*X2 + ... + a9*X9)mod4 = (4-C)mod4。
然后高斯消元求解。
-------------------------------
消元的时候如果选择绝对值最大的那一列就会wa,原因思考了一下,
如果我们的数据是
0 0 0
0 0 0
0 0 2
那么选择最大值与不选最大值得出的结果是不一样的。
我们观察他们的最终矩阵
选最大值:
1 1 0 1 0 0 0 0 0 0 0 3 0 0 1 0 1 0 0 0 0 0 3 0 3 3 3 0 0 0 0 0 0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0 3 0 0 0 0 0 0 3 0 1 0 0 0 0 0 0 0 0 1 0 3 0 0 0 0 0 0 0 0 2 3 2 0 0 0 0 0 0 0 0 3 2
不选最大值:
1 1 0 1 0 0 0 0 0 0 0 1 1 0 0 1 0 0 0 0 0 0 1 3 1 0 0 0 0 0 0 0 0 1 0 1 1 0 0 0 0 0 0 0 3 0 0 0 1 0 0 0 0 0 0 3 0 1 0 0 0 0 0 0 0 0 3 0 1 0 0 0 0 0 0 0 0 3 1 0 0 0 0 0 0 0 0 0 3 2
可以发现不选最大值的矩阵中A[i][i]刚好都为1或3,而选最大值的矩阵中出现了一个A[7][7]=2。
可这道题所取的模为4,这样的话,由于我们消元与最终求解时都需要用到A[i][i],所以当有A[i][i]=2时我们并不能保证最终结果是正确的。
因为已知p是素数时,模p剩余系里每个除0以外的元素都有唯一的逆,但p不为素数时,比如这道题的模4,2就没有逆。
所以其实选最大值时跳过2也可以过。
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <stack> #include <bitset> #include <queue> #include <set> #include <map> #include <string> #include <algorithm> #define FOP freopen("data.txt","r",stdin) #define FOP2 freopen("data1.txt","w",stdout) #define inf 0x3f3f3f3f #define maxn 310 #define mod 4 #define PI acos(-1.0) #define LL long long using namespace std; typedef int Matrix[maxn][maxn]; int x[maxn]; int sum; int gcd(int a, int b) { return b == 0 ? a : gcd(b, a%b); } int lcm(int a, int b) { return a / gcd(a, b) * b; //防溢出 } //equ个方程,var个变元 A[r][c], 0<r<equ, 0<c<var int gauss_elimination(Matrix A, int equ, int var) { memset(x, 0, sizeof(x)); int row, col; //当前处理的行row和列col int max_r; for(row = 0, col = 0; row < equ && col < var; row++, col++) { if(A[row][col] == 0) { for(int r = row+1; r < equ; r++) if(A[r][col]) { for(int c = 0; c <= var; c++) swap(A[row][c],A[r][c]); break; } } //与第row+1~equ行进行消元 int LCM, ta, tb; for(int r = row+1; r < equ; r++) { if(A[r][col] == 0) continue; LCM = lcm(abs(A[r][col]),abs(A[row][col])); ta = LCM / abs(A[r][col]); tb = LCM / abs(A[row][col]); if(A[r][col] * A[row][col] < 0) tb = -tb;//异号的情况是相加 for(int c = col; c <= var; c++) { A[r][c] = A[r][c] * ta - A[row][c] * tb; A[r][c] = (A[r][c]%mod+mod)%mod; } } } int temp; for (int r = var - 1; r >= 0; r--) { temp = A[r][var]; for(int c = r + 1; c < var; c++) { if (A[r][c] != 0) temp -= x[c] * A[r][c]; temp = (temp%mod+mod)%mod; } while(temp % A[r][r] != 0) temp += mod; //剩余系的特殊处理 x[r] = (temp / A[r][r])%mod; sum += x[r]; } return 0; } Matrix A; int vis[][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 }; int cot; int main() { int t, n = 9; for(int i = 0; i < n; i++) { for(int j = 0; j < n; j++) A[i][j] = vis[i][j]; scanf("%d", &t); A[i][n] = (mod - t)%mod; } gauss_elimination(A, n, n); for(int i = 0; i < n; i++) { while(x[i]--) { printf("%d", i+1); sum--; printf(sum > 0 ? " " : "\n"); } } return 0; }
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <stack> #include <bitset> #include <queue> #include <set> #include <map> #include <string> #include <algorithm> #define FOP freopen("data.txt","r",stdin) #define FOP2 freopen("data1.txt","w",stdout) #define inf 0x3f3f3f3f #define maxn 310 #define mod 4 #define PI acos(-1.0) #define LL long long using namespace std; typedef int Matrix[maxn][maxn]; int x[maxn]; int sum; int gcd(int a, int b) { return b == 0 ? a : gcd(b, a%b); } int lcm(int a, int b) { return a / gcd(a, b) * b; //防溢出 } //equ个方程,var个变元 A[r][c], 0<r<equ, 0<c<var int gauss_elimination(Matrix A, int equ, int var) { memset(x, 0, sizeof(x)); int row, col; //当前处理的行row和列col int max_r; for(row = 0, col = 0; row < equ && col < var; row++, col++) { //找到该col列元素绝对值最大的那行与第row行交换,提高数值稳定性 max_r = row; for(int r = row+1; r < equ; r++) { if(abs(A[r][col]) > abs(A[max_r][col]) && A[r][col] != 2) max_r = r; //跳过2 } if(max_r != row) for(int c = 0; c <= var; c++) swap(A[max_r][c], A[row][c]); //与第row+1~equ行进行消元 int LCM, ta, tb; for(int r = row+1; r < equ; r++) { if(A[r][col] == 0) continue; LCM = lcm(abs(A[r][col]),abs(A[row][col])); ta = LCM / abs(A[r][col]); tb = LCM / abs(A[row][col]); if(A[r][col] * A[row][col] < 0) tb = -tb;//异号的情况是相加 for(int c = col; c <= var; c++) { A[r][c] = A[r][c] * ta - A[row][c] * tb; A[r][c] = (A[r][c]%mod+mod)%mod; } } } int temp; for (int r = var - 1; r >= 0; r--) { temp = A[r][var]; for(int c = r + 1; c < var; c++) { if (A[r][c] != 0) temp -= x[c] * A[r][c]; temp = (temp%mod+mod)%mod; } while(temp % A[r][r] != 0) temp += mod; //剩余系的特殊处理 x[r] = (temp / A[r][r])%mod; sum += x[r]; } return 0; } Matrix A; int vis[][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 }; int cot; int main() { int t, n = 9; for(int i = 0; i < n; i++) { for(int j = 0; j < n; j++) A[i][j] = vis[i][j]; scanf("%d", &t); A[i][n] = (mod - t)%mod; } gauss_elimination(A, n, n); for(int i = 0; i < n; i++) { while(x[i]--) { printf("%d", i+1); sum--; printf(sum > 0 ? " " : "\n"); } } return 0; }