题解:遗忘之祭仪
基本思路:
由于所有x都要被击中且不可以打到不要求的点以及图外,所以原图一定可以被若干个不相交的ab矩阵覆盖,由于每个点都要覆盖一次,那么可以考虑从mn矩阵中左上角开始匹配,匹配不上就输出“No”,匹配上就将对应的x消掉即可。
代码:
代码
#include<bits/stdc++.h>
using namespace std;
namespace STD
{
#define rr register
#define inf INT_MAX
#define scanf ybbb=scanf
typedef long long ll;
const int N=1004;
int t,ybbb;
int n,m,a,b;
char mat[N][N],base[N][N];
int ha=inf,ta=-inf,la=inf,ra=-inf;
int y;
template<typename X>
X cmax(X a_,X b_){return a_>b_?a_:b_;}
template<typename X>
X cmin(X a_,X b_){return a_<b_?a_:b_;}
int read()
{
rr int x_read=0,y_read=1;
rr char c_read=getchar();
while(c_read<'0'||c_read>'9')
{
if(c_read=='-') y_read=-1;
c_read=getchar();
}
while(c_read<='9'&&c_read>='0')
{
x_read=(x_read<<3)+(x_read<<1)+(c_read^48);
c_read=getchar();
}
return x_read*y_read;
}
bool check(int i,int j)
{
int p=i,q=j-(y-la);
int d=ha,f=la;
//cout<<p<<' '<<q<<' '<<d<<' '<<f<<'\n';
while(p-i<=ta-ha)
{
while(q-(j-(y-la))<=ra-la)
{
if(f<=0||f>ra) return 0;
if(base[d][f]=='x'&&mat[p][q]!='x') return 0;
if(base[d][f]=='x'&&mat[p][q]=='x') mat[p][q]='.';
q++;
f++;
// cout<<"SSS: "<<q<<' '<<f<<'\n';
}
q=j-(y-la);
f=la;
d++;
p++;
}
return 1;
}
};
using namespace STD;
int main()
{
t=read();
while(t--)
{
n=read(),m=read(),a=read(),b=read();
y=0,ha=inf,ta=-inf,la=inf,ra=-inf;
for(rr int i=1;i<=n;i++)
scanf("%s",mat[i]+1);
for(rr int i=1;i<=a;i++)
scanf("%s",base[i]+1);
bool yes=1;
for(rr int i=1;i<=a;i++)
{
for(rr int j=1;j<=b;j++)
{
if(base[i][j]=='x')
{
if(!y) y=j;
la=cmin(la,j);
ra=cmax(ra,j);
ha=cmin(i,ha);
ta=cmax(ta,i);
}
}
}
for(rr int i=1;i<=n;i++)
for(rr int j=1;j<=m;j++)
if(mat[i][j]=='x')
if(!check(i,j))
{
yes=0;
i=j=inf-4;
}
for(rr int i=1;i<=n;i++)
for(rr int j=1;j<=m;j++)
if(mat[i][j]=='x')
{
yes=0;
i=j=inf-3;
}
if(yes) printf("Yes\n");
else printf("No\n");
}
}
/*
考虑一个指针扫一遍整个mn矩阵。
碰到为x的就停下,然后匹配,匹配过程中
消去x即可。
*/
后言:
考场上想到了要这么匹配,但是想的方法是用一个指针扫,扫到x时就匹配,记一下匹配成的位置然后从那里继续扫,这样是\(O(n^{2})\)但没法实现,太麻烦。
受题解启发,用一个指针扫,然后匹配到的消去,就变得容易实现了,实际跑出来的时间也是比较优秀的。
2021-07-31 06:10:58 星期六 现役