题解 征服
小清新送命题目
首先发现可以按照 \((x+y)\) 的奇偶性分成两张图,两张图之间是独立的
然后发现此刻在每张图上选一个点后,会分成四个子问题
发现本质不同(位置不同)的子问题个数是很少的,可以直接记搜
发现 \(O(r^3c^3)\)
点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 100010
#define fir first
#define sec second
#define pb push_back
#define ll long long
//#define int long long
int n, m;
char mp[110][110];
namespace force{
int top;
bool vis[110][110];
pair<int, int> sta[N];
const int dlt[][2]={{-1, -1}, {-1, 1}, {1, -1}, {1, 1}};
bool dfs() {
bool rest=0;
for (int i=1; i<=top; ++i) if (!vis[sta[i].fir][sta[i].sec]) rest=1;
if (!rest) return 0;
bool any=0;
for (int i=1; i<=top; ++i) if (!vis[sta[i].fir][sta[i].sec]) {
vector<pair<int, int>> tem;
vis[sta[i].fir][sta[i].sec]=1;
tem.pb(sta[i]);
for (int k=0; k<4; ++k)
for (int x=sta[i].fir+dlt[k][0],y=sta[i].sec+dlt[k][1]; x>=1&&x<=n&&y>=1&&y<=m&&!vis[x][y]; x+=dlt[k][0],y+=dlt[k][1])
vis[x][y]=1, tem.pb({x, y});
if (!dfs()) any=1;
for (auto& it:tem) vis[it.fir][it.sec]=0;
}
return any;
}
void solve() {
top=0;
memset(vis, 0, sizeof(vis));
for (int i=1; i<=n; ++i)
for (int j=1; j<=m; ++j)
if (mp[i][j]=='X')
sta[++top]={i, j};
int cnt=0;
for (int i=1; i<=top; ++i) {
vector<pair<int, int>> tem;
vis[sta[i].fir][sta[i].sec]=1;
tem.pb(sta[i]);
for (int k=0; k<4; ++k)
for (int x=sta[i].fir+dlt[k][0],y=sta[i].sec+dlt[k][1]; x>=1&&x<=n&&y>=1&&y<=m&&!vis[x][y]; x+=dlt[k][0],y+=dlt[k][1])
vis[x][y]=1, tem.pb({x, y});
if (!dfs()) ++cnt;
for (auto& it:tem) vis[it.fir][it.sec]=0;
}
// cout<<"cnt: "<<cnt<<endl;
int x=top-cnt, y=top;
x/=__gcd(cnt, top); y/=__gcd(cnt, top);
cout<<x<<' '<<y<<endl;
}
}
namespace task{
int l[3], r[3], u[3], d[3];
int id[110][110], bel[N], tot;
pair<int, int> pos[N], range[10];
bool iskey[510][510], vis[110][110];
map<pair<pair<int, int>, pair<int, int>>, int> mp2;
const int dlt[][2]={{-1, -1}, {-1, 1}, {1, -1}, {1, 1}};
const int dlt2[][2]={{0, -1}, {-1, 0}, {1, 0}, {0, 1}};
void dfs(int i, int j, int x, int y, int now) {
if (i<0||i>n+1||j<0||j>m+1||vis[i][j]) return ;
vis[i][j]=1;
if (i>=1&&i<=n&&j>=1&&j<=m&&!id[i][j]) {
pos[id[i][j]=++tot]={x, y};
bel[id[i][j]]=now;
iskey[x][y]=(mp[i][j]=='X');
// cout<<"ij: "<<i<<' '<<j<<endl;
// if (mp[i][j]=='X') cout<<"one"<<endl;
}
for (int k=0; k<4; ++k)
dfs(i+dlt[k][0], j+dlt[k][1], x+dlt2[k][0], y+dlt2[k][1], now);
}
int dfs(pair<pair<int, int>, pair<int, int>> mp) {
// cout<<"dfs: (("<<mp.fir.fir<<','<<mp.fir.sec<<"), ("<<mp.sec.fir<<','<<mp.sec.sec<<") "<<endl;
if (mp.fir.fir>mp.sec.fir || mp.fir.sec>mp.sec.sec) return 0;
if (mp2.find(mp)!=mp2.end()) return mp2[mp];
vector<int> sta;
for (int x=mp.fir.fir; x<=mp.sec.fir; ++x) {
for (int y=mp.fir.sec; y<=mp.sec.sec; ++y) if (iskey[x][y]) {
sta.pb(
dfs({mp.fir, {x-1, y-1}}) ^ dfs({{mp.fir.fir, y+1}, {x-1, mp.sec.sec}}) ^ dfs({{x+1, y+1}, mp.sec}) ^ dfs({{x+1, mp.fir.sec}, {mp.sec.fir, y-1}})
);
}
}
sort(sta.begin(), sta.end());
sta.erase(unique(sta.begin(), sta.end()), sta.end());
for (int i=0; ; ++i) if (i>=sta.size()||sta[i]!=i) return mp2[mp]=i;
}
void solve() {
tot=0;
memset(id, 0, sizeof(id));
memset(iskey, 0, sizeof(iskey));
memset(vis, 0, sizeof(vis));
mp2.clear();
memset(l, 127, sizeof(l));
memset(r, 128, sizeof(r));
memset(d, 127, sizeof(d));
memset(u, 128, sizeof(u));
dfs(1, 1, 100, 100, 1), range[1]={1, tot};
range[2]={tot+1, n*m}, dfs(1, 2, 300, 100, 2);
// cout<<"tot: "<<tot<<endl;
for (int i=1; i<=2; ++i) {
for (int j=range[i].fir; j<=range[i].sec; ++j) {
bel[j]=i;
l[i]=min(l[i], pos[j].fir);
r[i]=max(r[i], pos[j].fir);
u[i]=max(u[i], pos[j].sec);
d[i]=min(d[i], pos[j].sec);
}
}
// {{l[i], d[i]}, {r[i], u[i]}}
int all=0;
for (int i=1; i<=n; ++i) for (int j=1; j<=m; ++j) all+=(mp[i][j]=='X');
// cout<<"all: "<<all<<endl;
int cnt=0;
for (int i=1; i<=2; ++i) {
// cout<<"i: "<<i<<endl;
pair<pair<int, int>, pair<int, int>> now={{l[i], d[i]}, {r[i], u[i]}};
for (int x=l[i]; x<=r[i]; ++x) {
for (int y=d[i]; y<=u[i]; ++y) if (iskey[x][y]) {
// cout<<"point: ("<<x<<','<<y<<")"<<endl;
int sg=dfs({now.fir, {x-1, y-1}})^dfs({{now.fir.fir, y+1}, {x-1, now.sec.sec}})^dfs({{x+1, y+1}, now.sec})^dfs({{x+1, now.fir.sec}, {now.sec.fir, y-1}})^dfs({{l[i^3], d[i^3]}, {r[i^3], u[i^3]}});
// cout<<"sg: "<<sg<<endl;
if (!sg) ++cnt;
}
}
}
int gcd=__gcd(all-cnt, all);
printf("%d %d\n", (all-cnt)/gcd, all/gcd);
// cout<<mp[5][3]<<endl;
}
}
int main()
{
freopen("conquer.in", "r", stdin);
freopen("conquer.out", "w", stdout);
int T;
scanf("%d", &T);
while (T--) {
scanf("%d%d", &n, &m);
for (int i=1; i<=n; ++i) scanf("%s", mp[i]+1);
// force::solve();
task::solve();
}
return 0;
}