C - Matrix Reducing (atcoder.jp)
题目大意就是:
给AB两个矩阵,问A删掉任意行列能不能得到B
好久不被C题卡住了,wa了六发,想到dp去了,卡在元素重复的问题。
3000多人能过的题,我还是太菜了。。。
其实可以暴力遍历,赛时我也想到可以按题意模拟删边删列,但我的思路变成12345这5列取3列删掉,然后有点像dfs求全排列,后来感觉有点麻烦就不用了。
没想到可以用位运算完美解决。每次+1,然后00001,00010,00011,……,10110这种,可以把0直接看成被删掉的行列。
然后这个时候就不要想着十进制转二进制了,思路转过来,可以用((1<<k)&i)==0来实现删除边的判断。
就解决了,位运算还是太薄弱了,主要是被以前思维固化了。
主要代码展示
const int N=15;
int a[N][N],b[N][N];
void work(){
int n,m;cin>>n>>m;
rep(i,1,n) rep(j,1,m) cin>>a[i][j];
int h,w;cin>>h>>w;
rep(i,1,h) rep(j,1,w) cin>>b[i][j];
for (int i=0;i<(1<<n);i++){
for (int j=0;j<(1<<m);j++){
vector<int> ve1,ve2;
rep(k,1,n) if((1<<(k-1)&i)==0) ve1.push_back(k);
rep(k,1,m) if((1<<(k-1)&j)==0) ve2.push_back(k);
if (ve1.size()!=h||ve2.size()!=w) continue;
int f=0;
for (int u=1;u<=h;u++){
for (int v=1;v<=w;v++){
if (a[ve1[u-1]][ve2[v-1]]!=b[u][v]){
f=1;
break;
}
}
}
if (f==0){
cout<<"Yes"<<endl;
return;
}
}
}
cout<<"No"<<endl;
}