【题解】codeforces 1236 - D. Alice and the Doll

题目链接

这道题思路很简单,但是要把代码写得简洁,清晰,却不容易!

题解

直接模拟整个过程。走的时候记录走过的格子,最后检查总数是否等于总格子数-障碍数
模拟时用set加速查找过程
然而,本题有四个方向,我一开始就习惯性的四个方向分开讨论,于是写了100多行。调起来比较麻烦
最简单的写法是旋转矩阵(只要坐标对应旋转,相对位置是不变的,所以矩形内部的任何信息都没有发生变化)
然后就只考虑处理向右的情况

这种做法是在 @juniorcompressor 的代码中学到的

//需在C++17以上版本编译
#include<bits/stdc++.h>
using namespace std;
#define PB push_back
#define lowbit(x) (x&(-x))
#define MP make_pair
#define fi first
#define se second
#define ls(x) (x << 1)
#define rs(x) ((x << 1) | 1)
#define rep(i,l,r) for (int i = l ; i <= r ; i++)
#define down(i,r,l) for (int i = r ; i >= l ; i--)
#define fore(i,x) for (int i = head[x] ; i ; i = e[i].next)
#define SZ(v) (int)v.size()

typedef long long ll;
typedef pair <int,int> pr;
const int maxn = 1e6 + 10;

vector <set<ll>> obstacles(4);
int n,m,k;

bool solve(){
	ll num = (ll)n * m - k;
	int l = 0 , r = m , u = 0 , d = n;
	for (int i = 0; l < r and u < d ; i = (i + 1) % 4){
		ll p = (ll)u * m + l;
		auto it = obstacles[i].lower_bound(p);
		int nxtr = (it == obstacles[i].end()) ? r : min((ll)r,*it - p + l);
		num -= nxtr - l;
		tie(l,r,u,d,n,m) = tuple(u + 1,d,m - nxtr,m - l,m,n); //旋转,注意当前的信息是和边界的相对位置。要把这个推清楚
	}
	//cout<<num<<endl;
	return num == 0;
}
int main(){
	ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0);

	cin>>n>>m>>k;
	rep(i,1,k){
		int x,y;
		cin>>x>>y; x--, y--;
		for (auto &s : obstacles){ //建立四个方向的set,都是旋转到使得查询方向向右(每次逆时针转90度)
			s.insert((ll)m * x + y);
			tie(x,y,n,m) = tuple(m - 1 - y,x,m,n); 
		}
	}
	cout<<(solve() ? "Yes" : "No")<<"\n";
}

以前的分类讨论代码,巨长,且难调

#include<bits/stdc++.h>
using namespace std;
#define PB push_back
#define lowbit(x) (x&(-x))
#define MP make_pair
#define fi first
#define se second
#define ls(x) (x << 1)
#define rs(x) ((x << 1) | 1)
#define rep(i,l,r) for (int i = l ; i <= r ; i++)
#define down(i,r,l) for (int i = r ; i >= l ; i--)
#define fore(i,x) for (int i = head[x] ; i ; i = e[i].next)
#define SZ(v) (int)v.size()

typedef long long ll;
typedef pair <int,int> pr;
const int maxn = 1e5 + 10;
const ll mod = 1e9 + 7;

int n,m,k;
set <int> row[maxn],col[maxn];
ll sum;

//1 : right
//2 : down
//3 : left
//4 : up

int getR(set <int> &s,int p){
	auto it = s.upper_bound(p);
	assert(it != s.end());
	return *it;
}
int getL(set <int> &s,int p){
	auto it = s.lower_bound(p);
	assert(it != s.begin());
	return *(--it);
}
void solve(int x,int y,int dir,int U,int D,int L,int R){
	//cout<<x<<" "<<y<<" "<<dir<<" "<<U<<" "<<D<<" "<<L<<" "<<R<<" "<<sum<<"\n";
	if ( dir > 4 ) dir = 1;
	if ( dir == 1 ){
		int r = getR(row[x],y);
		r = min(r - 1,R);
		if ( r <= y ) return;
		sum += r - y;
		solve(x,r,2,U + 1,D,L,r);
	}
	if ( dir == 2 ){
		int r = getR(col[y],x);
		r = min(r - 1,D);
		if ( r <= x ) return;
		sum += r - x;
		solve(r,y,3,U,r,L,R - 1);
	}
	if ( dir == 3 ){
		int l = getL(row[x],y);
		l = max(l + 1,L);
		if ( l >= y ) return;
		sum += y - l;
		solve(x,l,4,U,D - 1,l,R);
	}
	if ( dir == 4 ){
		int l = getL(col[y],x);
		l = max(l + 1,U);
		if ( l >= x ) return;
		sum += x - l;
		solve(l,y,1,l,D,L + 1,R);
	}
}
int main(){
	//freopen("input.txt","r",stdin);
	ios::sync_with_stdio(false);
	cin>>n>>m>>k;

	int a[10][10];
	rep(i,1,k){
		int x,y;
		cin>>x>>y;
		row[x].insert(y);
		col[y].insert(x);
		//a[x][y] = 1;
	}
	/*rep(i,1,n){
		rep(j,1,m){
			cout<<a[i][j];
		}
		cout<<endl;
	}*/
	rep(i,1,n) row[i].insert(0) , row[i].insert(m + 1);
	rep(i,1,m) col[i].insert(0) , col[i].insert(n + 1);
	sum = 1;
	solve(1,1,1,1,n,1,m);
	if ( sum == (ll)n * m - k ) cout<<"Yes\n";
	else{
		sum = 1;
		solve(1,1,2,1,n,1,m);
	 	if ( sum == (ll)n * m - k ) cout<<"Yes\n";
	 	else cout<<"No\n";
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值