1.POJ-1222 EXTENDED LIGHTS OUT
题意
开关问题,给一个矩阵,每次翻转,上下左右都会一起翻转,问你翻转哪些位置,可以把灯全部关上。
思路
异或运算下的高斯消元
典型的开关问题,和 POJ 1830 开关问题 是一样的属于 XOR 类型的消元。
/***************************
*author:ccf
*source:poj-1222- EXTENDED LIGHTS OUT
*topic:高斯消元
****************************/
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#define ll long long
using namespace std;
const int N = 40;
const int inf = 50;
int cas,n,icas = 1;
int a[N][N];//增广矩阵
int equ,var;//equ:行 var: 列
int free_i[N],free_cnt;
int x[N],mp[N];//x[N]自由元数组
//void debug() {
// for(int i = 0 ; i < equ; i++) {
// for(int j = 0; j <= var; j++)
// printf("%d ",a[i][j]);
// printf("\n");
// }
//
//}
bool Gauss() {
int k,col,max_i;//k是列 col是行 max_i是最大行
//转化为阶梯阵
for(k = col = 0; k < equ && col < var; k++,col++) {
//找到最大行
max_i = k;
for(int i = k + 1; i < equ; i++) {
if(abs(a[i][col]) > abs(a[max_i][col])) max_i = i;
}
if(a[max_i][col] == 0) {
free_i[col] = 1;
x[free_cnt++] = col;
k--;
continue;
}
if(k != max_i) {
for(int j = col; j <= var; j++) {
swap(a[max_i][j],a[k][j]);
}
}
//开始化简阶梯阵
for(int i = 0; i < equ; i++) {
if(a[i][col] && i != k)
for(int j = col; j <= var; j++)
a[i][j] ^= a[k][j];
}
}
//debug();
for(int i = k; i < equ; i++)
if(a[i][var]) return false;
return true;
}
int main() {
//freopen("date.in","r",stdin);
equ = var = 30;
scanf("%d",&cas);
while(cas--) {
int cnt = 0;
memset(a,0,sizeof(a));
memset(free_i,0,sizeof(free_i));
memset(x,0,sizeof(x));
memset(mp,0,sizeof(mp));
for(int i = 0; i < equ; i++) {
scanf("%d",&mp[i]);
a[i][var] = mp[i];
}
//方格化成增广矩阵
for(int i = 0 ; i < equ; i++) {
a[i][i] = 1;
if(i < 24) a[i][i+6] = 1;
if(i > 5) a[i][i-6] = 1;
if(i % 6 != 0) a[i][i-1] = 1;
if(i % 6 != 5) a[i][i+1] = 1;
}
if(!Gauss()) printf("no solution!\n");
else {
printf("PUZZLE #%d\n",icas++);
for(int i = 1; i <= 30; i++) {
printf("%d",a[i-1][var]);
if(i % 6 == 0) printf("\n");
else printf(" ");
}
}
}
return 0;
}
2.POJ-2947-Widget Factory
题意
有n种饰品,每种的加工时间为3~9天,现在知道m条记录,每条记录形如:开始时间是周几,终止时间是周几,加工出来哪些饰品,各多少件。但是不知道持续了多少周。
求每种饰品的加工时间。
需要判断无解和多解。
思路
高斯消元解同余方程
在原本高斯约旦消元的基础上,加上取模的运算,最后每一行得到一个
A x ≡ C ( m o d p ) Ax\equiv C(mod p) Ax≡C(modp)形式的式子,使用扩展欧几里得解同余方程即可,也有直接模拟取余操作的方法。
/***********************
*author:ccf
*source:poj-2974 Widget Factory
*topic:高斯消元解同余方程
************************/
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#define ll long long
using namespace std;
const int N = 600;
int cas,n,m,icas;
char start[5],fired[5];
int a[N][N],ans[N];//行列式 解集
int equ,var,free_cnt = 0;
void debug() {
for(int i = 1; i <= equ; i++) {
for(int j = 1; j <= var + 1; j++) {
printf("%d ",a[i][j]);
}
printf("\n");
}
printf("\n");
}
int sti(char *s) {
if(strcmp(s, "MON") == 0) return 1;
else if(strcmp(s, "TUE") == 0) return 2;
else if