【NKOJ1987 POJ1681】手机游戏(Painter's Problem) 高斯消元
高斯消元,消来消去真有趣,突然想去玩祖玛。
POJ传送门http://poj.org/problem?id=1681
NKOJ传送门http://oi.nks.edu.cn/zh/Problem/Details/1987
一个高斯消元解异或方程组板题。
真的没有什么好说的。就说说时间复杂度。看似O(n6)的时间复杂度,但我们可以注意到,每一个点最多关联上下左右自己5个方程式,也就说实际上它的时间复杂度是O(n4)加上一个常数(可见大概为5)。
记得要枚举自由元!用DFS比较好理解,也有状压的写法,DFS原型来自ciocio学长。
#include<cstring>
#include<iostream>
#include<cstdio>
using namespace std;
int n,N,X[2005];
int A[2005][2005];
int dx[4]={1,-1,0,0};
int dy[4]={0,0,-1,1};
int aha=0;
int minn; int num[2005];
int ans[2005];
void dfs(int x,int y)
{
if(x==0&&y==0)
{
int cnt=0;
for(int i=1;i<=N;i++) cnt+=ans[i];
minn=min(minn,cnt);
return;
}
if(num[x]==y)
{
ans[y]=A[x][N+1];
for(int i=y+1;i<=N;i++) ans[y]^=(A[x][i]&ans[i]);
dfs(x-1,y-1);
}
else
{
ans[y]=1; dfs(x,y-1);
ans[y]=0; dfs(x,y-1);
}
}// from ciocio
void gauss()
{
int x,y,maxr;
for(x=1,y=1;x<=N&&y<=N;x++,y++)
{
for(maxr=x;maxr<=N&&(!A[maxr][y]);maxr++);
if(maxr==N+1) { x--; continue; }
if(maxr!=x)
for(int j=y;j<=N+1;j++) swap(A[x][j],A[maxr][j]);
num[x]=y;
for(int i=x+1;i<=N;i++)
{
if(A[i][y])
for(int j=y;j<=N+1;j++) A[i][j]^=A[x][j];
}
}
for(int i=x;i<=N;i++) if(A[i][N+1]) { printf("inf\n"); return; };
minn=0x3f3f3f3f;
dfs(x-1,N);
printf("%d\n",minn);
}
int main()
{
char ch;
scanf("%d",&n);
N=n*n;
for(int i=1;i<=n*n;i++) A[i][n*n+1]=1;
int nx,ny;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
for(int tt=0;tt<4;tt++)
{
nx=i+dx[tt]; ny=j+dy[tt];
if(nx>=1&&ny>=1&&nx<=n&&ny<=n)
{
A[(i-1)*n+j][(nx-1)*n+ny]=1;
}
}
A[(i-1)*n+j][(i-1)*n+j] = 1;
}
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
ch=getchar();
while(ch!='y'&&ch!='w') ch=getchar();
if(ch=='y') A[(i-1)*n+j][N+1]=0;
else A[(i-1)*n+j][N+1]=1;
}
}
gauss();
}

浙公网安备 33010602011771号