CodePlus 第五次網路賽 我有矩陣,你有嗎?(思維題)
題目描述
企鵝豆豆手裡有兩個 01 矩陣 A 和 B 。他可以進行兩種操作:
- 選擇 A 矩陣的一行,然後把這一行的 0 變成 1 ,把 1 變成 0 。
- 選擇 A 矩陣的一列,然後把這一列的 0 變成 1 ,把 1 變成 0 。
現在他想知道能不能把 A 矩陣通過以上操作變成 B 矩陣。保證 A 矩陣和 B 矩陣的大小一致。
輸入格式
從標準輸入讀入資料。
每個測試點只有一組資料。
輸入的第一行包含兩個正整數 n 和 m ,表示 A 矩陣的行數,保證 n≤103 ,m≤103 。 接下來 n 行,每行 m 個由空格隔開的整數,表示矩陣 A 。保證矩陣中只有 0 或者 1 。 接下來 n 行,每行 m 個由空格隔開的整數,表示矩陣 B 。保證矩陣中只有 0 或者 1 。
輸出格式
輸出到標準輸出。
如果矩陣 A 通過以上兩種操作可以變成矩陣 B ,輸出 Koyi
,否則輸出 Budexing
。
樣例1輸入
3 3
1 0 1
1 1 0
0 1 0
1 1 0
0 1 0
1 1 0
樣例1輸出
Koyi
解析:
雖然是一道很簡單的題目,但我太菜了,想了一個多小時才想出來...所以記錄一下自己和大佬的做法
首先都是先處理出差別的矩陣dif,a,b不相同的位置標1,
我的想法是第一行都用列解決。如果第一行有差異的位置,那麼就把對應這一列都變一次。
然後剩下的2-n行,再用行解決,如果剩下的2-n行,還有差異的,那把這一行都變一次。
這樣無論是怎麼的變換,都可以通過我這種方法轉換到。
因為如果需要列變換的,我一定是有的。剩下的就是不需要列變換,只需要變換第一行,那麼我再把下面的行都進行
行變換補回來就可以了。另外一種情況就是正解1:第一行變換,加上幾個列變換,那麼用我這種方法,就剛剛好
把正解1裡面沒有列變換的那幾列變換了,有變換的列沒有變換。但是這個你試一下就知道,可以互相轉換的。
只要n-2行你加行變換就可以等價轉換成正解1了。
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int MAXN = 1e3+100; int a[MAXN][MAXN]; int row[MAXN]; int col[MAXN]; int vis[MAXN]; int main() { int n,m; scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) { scanf("%d",&a[i][j]); } } for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) { int tmp; scanf("%d",&tmp); a[i][j]^=tmp; } } for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) { if(a[i][j]) { row[i]++; col[j]++; } } } for(int j=1;j<=m;j++) { if(a[1][j]) { for(int k=1;k<=n;k++) { a[k][j]^=1; } } } for(int i=2;i<=n;i++) { if(a[i][1]) { for(int j=1;j<=m;j++) a[i][j]^=1; } } int flag=1; for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) { if(a[i][j]==1) { flag=0; break; } } if(!flag) break; } if(flag) printf("Koyi\n"); else printf("Budexing\n"); }
下面是大佬1的做法,對於dif的每一行,最多隻可能有2種狀態。無論有沒有進行列變換,dif矩陣進行行變換的和沒有行變換的行。那麼進行行變換的行,對應那一行的dif的值一定是相同的。同理沒有進行行變換的也應該是相同的。
那麼我們只需要記錄這兩個狀態就好了。列同理
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
const int N=1010;
int a[N][N],n,m,can;
int main(){
cin>>n>>m;
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++)scanf("%d",&a[i][j]);
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++){
int x;
scanf("%d",&x);
a[i][j]^=x;
}
can=1;
int std1=-1,std2=-1;
for (int i=1;i<=n;i++){
int cnt=0;
for (int j=1;j<=m;j++)cnt+=a[i][j];
if (cnt==std1||cnt==std2)continue;
if (std1==-1){
std1=cnt;
continue;
}
if (std2==-1){
std2=cnt;
continue;
}
can=0;
}std1=-1;std2=-1;
for (int i=1;i<=m;i++){
int cnt=0;
for (int j=1;j<=n;j++)cnt+=a[j][i];
if (cnt==std1||cnt==std2)continue;
if (std1==-1){
std1=cnt;
continue;
}
if (std2==-1){
std2=cnt;
continue;
}
can=0;
}
printf(can?"Koyi\n":"Budexing\n");
}
大佬2:大佬2是使用了並查集。如果dif矩陣中為1的行i和列j,就加入一個並查集。處理之後,dif[i][j]=0的行i和列j 一定不在一個並查集裡面,這個自己舉幾個例子就知道了。
/*
Author: CNYALI_LK
LANG: C++
PROG: A.cpp
Mail: [email protected]
*/
#include<bits/stdc++.h>
#define debug(...) fprintf(stderr,__VA_ARGS__)
#define DEBUG printf("Passing [%s] in LINE %d\n",__FUNCTION__,__LINE__)
#define Debug debug("Passing [%s] in LINE %d\n",__FUNCTION__,__LINE__)
#define all(x) x.begin(),x.end()
#define x first
#define y second
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int inf=0x3f3f3f3f;
const double eps=1e-8;
const double pi=acos(-1.0);
template<class T>int chkmin(T &a,T b){return a>b?a=b,1:0;}
template<class T>int chkmax(T &a,T b){return a<b?a=b,1:0;}
template<class T>T sqr(T a){return a*a;}
template<class T>T mmin(T a,T b){return a<b?a:b;}
template<class T>T mmax(T a,T b){return a>b?a:b;}
template<class T>T aabs(T a){return a<0?-a:a;}
template<class T>int dcmp(T a,T b){return a>b;}
template<int *a>int cmp_a(int x,int y){return a[x]<a[y];}
#define min mmin
#define max mmax
#define abs aabs
namespace io {
const int SIZE = (1 << 21) + 1;
char ibuf[SIZE], *iS, *iT, obuf[SIZE], *oS = obuf, *oT = oS + SIZE - 1, c, qu[55]; int f, qr;
// getchar
#define gc() (iS == iT ? (iT = (iS = ibuf) + fread (ibuf, 1, SIZE, stdin), (iS == iT ? EOF : *iS ++)) : *iS ++)
// print the remaining part
inline void flush () {
fwrite (obuf, 1, oS - obuf, stdout);
oS = obuf;
}
// putchar
inline void putc (char x) {
*oS ++ = x;
if (oS == oT) flush ();
}
// input a signed integer
inline void read (int &x) {
for (f = 1, c = gc(); c < '0' || c > '9'; c = gc()) if (c == '-') f = -1;
for (x = 0; c <= '9' && c >= '0'; c = gc()) x = x * 10 + (c & 15); x *= f;
}
inline void read (char &x) {
x=gc();
}
inline void read(char *x){
while((*x=gc())=='\n' || *x==' '||*x=='\r');
while(!(*x=='\n'||*x==' '||*x=='\r'))*(++x)=gc();
}
template<typename A,typename ...B>
inline void read(A &x,B &...y){
read(x);read(y...);
}
// print a signed integer
inline void write (int x) {
if (!x) putc ('0'); if (x < 0) putc ('-'), x = -x;
while (x) qu[++ qr] = x % 10 + '0', x /= 10;
while (qr) putc (qu[qr --]);
}
inline void write (char x) {
putc(x);
}
inline void write(const char *x){
while(*x){putc(*x);++x;}
}
inline void write(char *x){
while(*x){putc(*x);++x;}
}
template<typename A,typename ...B>
inline void write(A x,B ...y){
write(x);write(y...);
}
//no need to call flush at the end manually!
struct Flusher_ {~Flusher_(){flush();}}io_flusher_;
}
using io :: read;
using io :: putc;
using io :: write;
int a[1023][1023],fa[2047];
int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);}
int main(){
#ifdef cnyali_lk
freopen("A.in","r",stdin);
freopen("A.out","w",stdout);
#endif
int n,m,x;
//read(n,m);
cin>>n>>m;
for(int i=1;i<=n;++i)for(int j=1;j<=m;++j)cin>>a[i][j];
for(int i=1;i<=n+m;++i)fa[i]=i;
for(int i=1;i<=n;++i)for(int j=1;j<=m;++j){cin>>x;a[i][j]^=x;if(a[i][j])fa[find(i)]=find(j+n);}
for(int i=1;i<=n;++i)for(int j=1;j<=m;++j)if(!a[i][j] && find(i)==find(j+n))return printf("Budexing\n"),0;
printf("Koyi\n");
return 0;
}
大佬3:大佬3的想法跟我是差不多的,只是他沒有把變換更新到矩陣裡面,而是存在s1,s2裡面
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;
int n,m;
int s[1005][1005],t[1005][1005];
int s1[1005],s2[1005];
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
scanf("%d",&s[i][j]);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
scanf("%d",&t[i][j]);
s1[0]=0;
for(int i=1;i<=m;i++)
s2[i]=s[1][i]^t[1][i];
for(int i=1;i<=n;i++)
s1[i]=s2[1]^s[i][1]^t[i][1];
int fl=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++){
if((s1[i]^s2[j])!=(s[i][j]^t[i][j])) fl=1;
}
if(fl) puts("Budexing");
else puts("Koyi");
return 0;
}