kmjp's blog

競技プログラミング参加記です

CodeQUEEN 2023 決勝 : D - Moving Queen

これは普通に自力で解けた。
https://atcoder.jp/contests/codequeen2023-final-open/tasks/codequeen2023_final_d

問題

R*Cのチェス盤を考える。
クイーンの初期位置と、停止位置が与えられる。
クイーンの移動を3回で、初期位置から停止位置に移動するような移動法は何通りか。

解法

初期位置から1回移動したセルを列挙しておく。
停止位置から1回移動したセルを列挙し、そのぞれぞれにおいて、もう1回移動すると「初期位置から1回移動したセル」のうち何個に移動可能かを求めればよい。

int R,C,RS,CS,RT,CT;

int Rs[101010];
int Cs[101010];
int RpCs[201010];
int RmCs[201010];
set<pair<int,int>> S;
vector<pair<int,int>> cand(int r,int c) {
	int y,x;
	vector<pair<int,int>> cand;
	FOR(y,R) if(y!=r) cand.push_back({y,c});
	FOR(x,C) if(x!=c) cand.push_back({r,x});
	
	FOR(y,R) if(y!=r) {
		x=c+(y-r);
		if(x>=0&&x<C) cand.push_back({y,x});
		x=c-(y-r);
		if(x>=0&&x<C) cand.push_back({y,x});
	}
	return cand;
}

void solve() {
	int i,j,k,l,r,x,y; string s;
	
	cin>>R>>C>>RS>>CS>>RT>>CT;
	RS--,RT--,CS--,CT--;
	vector<pair<int,int>> A=cand(RS,CS);
	vector<pair<int,int>> B=cand(RT,CT);
	
	FORR2(y,x,A) {
		S.insert({y,x});
		Rs[y]++;
		Cs[x]++;
		RpCs[y+x]++;
		RmCs[y-x+100000]++;
	}
	ll ret=0;
	FORR2(y,x,B) {
		if(S.count({y,x})) ret-=4;
		ret+=Rs[y];
		ret+=Cs[x];
		ret+=RpCs[y+x];
		ret+=RmCs[y-x+100000];
	}
	cout<<ret<<endl;
	
}

まとめ

Queen縛りとはいえ、Bと似すぎててちょっと食傷気味。