Codeforces Gym 100341I Hungry Queen 2 Set+模拟

题目大意:

在一个无穷大的棋盘上有一个皇后在(0,0)点,皇后可以上下左右或者沿对角线移动。有n个卒,皇后要按卒的输入顺序吃卒,每次移动必须吃掉一个卒,皇后不能跳过卒。问皇后最多能吃掉几个卒?

做法:

  • 先将所有卒的位置(x、y、x+y、x-y)离散化;
  • 用set分别记录,在同一行(按y排序)、同一列(按x排序)、同一对角线的卒;
  • 模拟皇后的移动,每次在当前位置与下一个卒的位置所确定的set中查找下一个卒的前驱和后继,如果前驱和后继中有一个是当前位置,这说明在当前位置与下一个卒的方向上没有障碍,答案+1;
  • 在所有方向的set中删掉当前点,然后移动到下一个点;
  • 反之,如果下一个卒与当前位置不能构成合法移动,或者在当前位置与下一个卒的方向上有障碍,那么就结束模拟输出答案。

代码:

4551665Accepted24532498GNU G++ 4.9.226065:06:16
#include <bits/stdc++.h>
using namespace std;
const int maxn=100001;
int x[maxn],y[maxn],lx[maxn],ly[maxn],lxpy[maxn],lxmy[maxn];
struct cmp2{
    bool operator ()(int a,int b)const
    {
        return x[a]<x[b];
    }
};
//按x排序 
struct cmp1{
    bool operator ()(int a,int b)const
    {
        return y[a]<y[b];
    }
};
//按y排序 
set<int,cmp1>mx[maxn],mxpy[maxn],mxmy[maxn];
set<int,cmp1>::iterator ix,ipx;
set<int,cmp2>my[maxn];
set<int,cmp2>::iterator iy,ipy;
int rp(int num,int l,int a[])
{
    return lower_bound(a,a+l,num)-a;
}
//返回离散化下标 
int main()
{
    freopen("queen2.in","r",stdin);
#ifdef ONLINE_JUDGE
    freopen("queen2.out","w",stdout);
#endif
    int n;
    scanf("%d",&n);
    for(int i=0;i<n;i++)
    {
        scanf("%d%d",&x[i],&y[i]);
        lx[i]=x[i];
        ly[i]=y[i];
        lxpy[i]=x[i]+y[i];
        lxmy[i]=x[i]-y[i];
    }
    sort(lx,lx+n);
    sort(ly,ly+n);
    sort(lxpy,lxpy+n);
    sort(lxmy,lxmy+n);
    int sx=unique(lx,lx+n)-lx;
    int sy=unique(ly,ly+n)-ly;
    int sxpy=unique(lxpy,lxpy+n)-lxpy;
    int sxmy=unique(lxmy,lxmy+n)-lxmy;
    //离散化 
    int px=0,py=0;
    for(int i=0;i<n;i++){
        mx[rp(x[i],sx,lx)].insert(i);
        my[rp(y[i],sy,ly)].insert(i);
        mxpy[rp(x[i]+y[i],sxpy,lxpy)].insert(i);
        mxmy[rp(x[i]-y[i],sxmy,lxmy)].insert(i);
    }
    //将同类点加到set中 

    //模拟移动 
    if(px==x[0] || py == y[0] || px+py ==x[0]+y[0] || px-py == x[0]-y[0]){
        int ans=1,ans2=0;
        px=x[0];py=y[0];
        for(int i=1;i<n;i++)
        {
            ans2=ans;   
            if(px == x[i])
            {
                int pos=rp(x[i],sx,lx);
                ix=++mx[pos].find(i);
                if(ix!=mx[pos].end() && (*ix) == (i-1))++ans;
                ipx=mx[pos].find(i);
                if( ipx!=mx[pos].begin() )
                    if(*(--ipx) == (i-1))++ans;
            }else if(py == y[i])
            {
                int pos=rp(y[i],sy,ly);
                iy=++my[pos].find(i);
                if(iy!=my[pos].end() && (*iy) == (i-1))++ans;
                ipy=my[pos].find(i);
                if( ipy!=my[pos].begin() )
                    if(*(--ipy) == (i-1))++ans;
            }else if(px+py == x[i]+y[i])
            {
                int pos=rp(x[i]+y[i],sxpy,lxpy);
                ix=++mxpy[pos].find(i);
                if(ix!=mxpy[pos].end() && (*ix) == (i-1))++ans;
                ipx=mxpy[pos].find(i);
                if( ipx!=mxpy[pos].begin() )
                    if(*(--ipx) == (i-1))++ans;
            }else if(px-py == x[i]-y[i])
            {
                int pos=rp(x[i]-y[i],sxmy,lxmy);
                ix=++mxmy[pos].find(i);
                if(ix!=mxmy[pos].end() && (*ix) == (i-1))++ans;
                ipx=mxmy[pos].find(i);
                if( ipx!=mxmy[pos].begin() )
                    if(*(--ipx) == (i-1))++ans;
            }
            else break;
            if(ans==ans2)break;
            mx[rp(px,sx,lx)].erase(i-1);
            my[rp(py,sy,ly)].erase(i-1);
            mxpy[rp(px+py,sxpy,lxpy)].erase(i-1);
            mxmy[rp(px-py,sxmy,lxmy)].erase(i-1);
            px=x[i];py=y[i];
        }
        printf("%d\n",ans);
    }else printf("0\n");
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值