题解 征服

传送门

小清新送命题目

首先发现可以按照 \((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;
}
posted @ 2022-07-02 21:09  Administrator-09  阅读(2)  评论(0编辑  收藏  举报