HYSBZ/BZOJ 3503 和谐矩阵 - 高斯约当消元异或方程
2016-02-01 18:55
405 查看
题目描述
2.代码 by Liu Junhao 这是他关于这道题的blog
Solution 1:
把矩阵中的每一个元素看作未知数,根据元素之间的互相影响列方程,方程大小为 (n*m,n*m)。如果有不定解怎么办呢?
1. dfs暴力枚举每一个不定解。肯定要TLE
2. 在每行确定解的时候,强制性设定这行的所有不定解为1 ,继续回代,直到出答案。 好像数据挺水,O((nm)3{(nm)}^3)勉强能过。
1.代码,但要T#include<cstdio> #include<cmath> #include<cstring> #include<algorithm> using namespace std; #define MAXN 1600 int dir[10][3]={{0,0},{0,1},{0,-1},{1,0},{-1,0}}; int n,m; int a[MAXN+10][MAXN+10],id[MAXN+10][MAXN+10],x[MAXN+10],p; void Structure() { int x,y; for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) id[i][j]=(i-1)*m+j; for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) for(int k=0;k<5;k++){ x=i+dir[k][0],y=j+dir[k][1]; if(x>=1&&x<=n&&y>=1&&y<=m) a[id[x][y]][id[i][j]]=1; } } void GJ_elimination(int equ,int var,int &row,int &col) { int mx; for(row=col=1;row<=equ&&col<=var;row++,col++){ mx=row; for(int i=row+1;i<=equ;i++){ if(a[i][col]>a[mx][col]) mx=i; if(a[mx][col]==1) break; } if(mx!=row) swap(a[row],a[mx]); if(a[row][col]==0){ //本题有唯一解,这句if可以不要 row--; continue; } for(int i=1;i<=equ;i++){ if(i==row||a[i][col]==0) continue; for(int j=var+1;j>=1;j--) a[i][j]^=a[row][j]; } } } int GJ_Judge(int equ,int var,int row,int col) { if(row<=var) return row; for(int i=row-1;i>=1;i--) x[i]=a[i][var+1]; return 0; } int Gauss_Jordan(int equ,int var) { int row,col; GJ_elimination(equ,var,row,col); return GJ_Judge(equ,var,row,col); } void print() { for(int i=1;i<=n*m;i++){ printf("%d",x[i]); if(i%m==0) printf("\n"); else printf(" "); } } bool check() { int cnt=0,tmp; for(int i=p-1;i>=1;i--){ tmp=0; for(int j=i+1;j<=n*m;j++) if(a[i][j]) tmp^=x[j]; x[i]=a[i][n*m+1]^tmp; if(!x[i]) cnt++; } for(int i=p;i<=n*m;i++) if(!x[i]) cnt++; if(cnt==n*m) return false; else return true; } void dfs(int u) { if(u>n*m){ if(check()){ print(); exit(0); } return ; } x[u]=1; dfs(u+1); x[u]=0; dfs(u+1); } int main() { scanf("%d%d",&n,&m); Structure(); p=Gauss_Jordan(n*m,n*m); if(!p) print(); else dfs(p); }
2.代码 by Liu Junhao 这是他关于这道题的blog
void gauss_jordan(){ int row,col,i,j,cnt; for(row=col=1;row<=equ&&col<=var;row++,col++){ if(!a[row][col]) for(i=row+1;i<=equ;i++) if(a[i][col]){ swap(a[row],a[i]); break; } if(!a[row][col]){ row--; continue; } for(i=1;i<=equ;i++) if(i!=row&&a[i][col]) for(j=var+1;j>=col;j--) a[i][j]^=a[row][j]; } row--; for(i=row;i;i--){ cnt=0; for(j=i;j<=var;j++) if(a[i][j]){ if(!vis[j]) cnt++; else a[i][var+1]^=x[j],a[i][j]=0; } for(j=i;j<=var;j++) if(a[i][j]){ if(--cnt) x[j]=1,a[i][var+1]^=1; else x[j]=a[i][var+1]; vis[j]=1; } } } void print(){ int i,j; for(i=1;i<=n;i++){ for(j=1;j<=m;j++) printf("%d ",x[(i-1)*m+j]); puts(""); } } int main() { read(); gauss_jordan(); print(); }
Solution 2:
将矩阵第一行的m个元素看作未知数,记为x1x_1 ~ xmx_m,由元素之间的互相影响可以推出其后的每个元素关于x1x_1 ~ xmx_m 的关系式,最后由剩下的m个影响关系得到m个关于x1x_1 ~ xmx_m 的方程,用高斯消元求解,O(m3m^3)的复杂度。
对于不定解的处理仍然有solution 1 中的两种方案,但方案1可用了,不会再超时,而且较solution快了不知多少倍。
可惜solution 2的代码太长,把Special Judge()去掉的话会好看一些#include<cstdio> #include<algorithm> using namespace std; #define MAXN 40 int dir[10][3]={{-2,0},{-1,0},{-1,-1},{-1,1}}; int dir2[10][3]={{0,0},{0,1},{0,-1},{-1,0}}; int n,m,a[MAXN+10][MAXN+10],x[MAXN+10]; int p[MAXN+10][MAXN+10][MAXN+10],cntx,ans[MAXN+10][MAXN+10]; void print(); void Represent() { int x,y; for(int j=1;j<=m;j++) p[1][j][j]=1; for(int i=2;i<=n;i++){ for(int j=1;j<=m;j++) for(int k=0;k<4;k++){ x=i+dir[k][0],y=j+dir[k][1]; if(!(x>=1&&x<=n&&y>=1&&y<=m)) continue; for(int t=1;t<=m;t++) p[i][j][t]^=p[x][y][t]; } } } void Structure() { int x,y; for(int j=1;j<=m;j++){ for(int k=0;k<4;k++){ x=n+dir2[k][0],y=j+dir2[k][1]; if(!(x>=1&&x<=n&&y>=1&&y<=m)) continue; for(int t=1;t<=m;t++) a[j][t]^=p[x][y][t]; } } } void GJ_elimination(int equ,int var,int &row,int &col) { int mx; for(row=col=1;row<=equ&&col<=var;row++,col++){ mx=row; for(int i=row+1;i<=equ;i++){ if(a[i][col]>a[mx][col]) mx=i; if(a[mx][col]==1) break; } if(mx!=row) swap(a[mx],a[row]); if(a[row][col]==0){ row--; continue; } for(int i=1;i<=equ;i++){ if(i==row||a[i][col]==0) continue; for(int j=1;j<=var+1;j++) a[i][j]^=a[row][j]; } } } int Gauss_Jordan(int equ,int var) { int row,col; GJ_elimination(equ,var,row,col); if(row<=var) return var-row+1; else return 0; } bool Judge() { int cnt0=0; for(int i=1;i<=n;i++) for(int j=1;j<=m;j++){ for(int k=1;k<=m;k++) if(p[i][j][k]) ans[i][j]^=x[k]; if(!ans[i][j]) cnt0++; } if(cnt0==n*m) return false; else return true; } bool check(int cntx) { int tmp; for(int i=m-cntx;i>=1;i--){ tmp=0; for(int j=i+1;j<=m;j++) if(a[i][j]) tmp^=x[j]; x[i]=a[i][m+1]^tmp; } return Judge(); } bool SpecialJudge() { int dr[10][6]={{0,0},{1,0},{-1,0},{0,1},{0,-1}}; for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ int tmp=0; for(int k=0;k<5;k++){ int x=i+dr[k][0],y=j+dr[k][1]; if(x>=1&&x<=n&&y>=1&&y<=m){ tmp^=ans[x][y]; } } if(tmp){ printf("%d %d\n",i,j); return false; } } } return true; } void print() { for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++) printf("%d ",ans[i][j]); puts(""); } /*if(SpecialJudge()) printf("Right\n"); else printf("Wrong\n");*/ } void dfs(int u) { if(u>m){ if(check(cntx)){ print(); exit(0); } return ; } x[u]=1; dfs(u+1); x[u]=0; dfs(u+1); } int main() { scanf("%d%d",&n,&m); Represent(); Structure(); cntx=Gauss_Jordan(m,m); if(cntx) dfs(m-cntx+1); else{ for(int i=1;i<=m;i++) x[i]=a[i][m+1]; print(); } return 0; }
相关文章推荐
- QVector 和vector的比较(QVector默认使用隐式共享,而且有更多的函数提供)
- nrf51822自学笔记(三)心率计
- 保护Android resources文件不被反编译原理分析
- android *** Layout 10 DatePicker && TimePicker
- 首次使用git配置说明
- vim用法详解
- Qt实现不同Treewidget之间拖拽
- maven工程小红叉处理方法
- gitlab添加用户
- 集成学习总结
- Hello World--------------LeapMotion API新建一个程序
- Qt实现QQ好友下拉列表(用QListView实现,所以还得定义它的Model)
- ZOJ 3875 LunchTime
- 基于spark机器学习---------物品推荐demo
- Gitlab客户端安装(for windows x64)
- 文件保存树形结构数据
- javac java在mac console中文乱码的问题
- Android自定义View控件
- Java环境的配置
- 用PHP写出显示客户端IP与服务器IP的代码