zoukankan      html  css  js  c++  java
  • noip模拟赛 柜(暴力)

    分析:暴力的方法是非常显然的,从起点走一次,从终点走一次,路径相交的点即为所求,但是这样存图都很难存下,而且如果数据极端可能要求R*C次,时间空间都受不了.如果不需要记录整张图,并且一次能移动很多步就好了,标程用了树状数组+set,我不是很懂,只能打一个暴力了.

    暴力:

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    const int maxn = 10010;
    const int dx[] = { 0, 0, 1, -1 }; 
    const int dy[] = { 1, -1, 0, 0 };
    int n, m, A, B, ansx, ansy, cnt;
    bool vis[maxn][maxn]; //512M的内存这数组应该是极限了.
    int a[maxn][maxn];
    
    struct node
    {
        int x, y;
    }e[maxn];
    
    bool cmp(node a, node b)
    {
        if (a.x == b.x)
            return a.y < b.y;
        return a.x < b.x;
    }
    
    void solve1()
    {
        int x = 1, y = 1, dir = 0;
        while (1)
        {
            if (a[x][y] == 1)
                dir = 3 - dir;
            if (a[x][y] == 2)
                dir = (dir + 2) % 4;
            vis[x][y] = 1;
            x = x + dx[dir], y = y + dy[dir];
            if (x > n || y > m || x < 1 || y < 1)
            {
                ansx = x;
                ansy = y;
                return;
            }
        }
    }
    
    void solve2()
    {
        int x = n, y = m, dir = 1;
        while (1)
        {
            if (a[x][y] == 1)
                dir = 3 - dir;
            if (a[x][y] == 2)
                dir = (dir + 2) % 4;
            if (vis[x][y] && !a[x][y])
            {
                e[++cnt].x = x;
                e[cnt].y = y;
                vis[x][y] = 0;
            }
            x += dx[dir], y += dy[dir];
            if (x > n || y > m || x < 1 || y < 1)
                return;
        }
    }
    
    int main()
    {
        while (scanf("%d", &n) != EOF)
        {
            scanf("%d%d%d", &m, &A, &B);
            cnt = 0;
            ansx = 0;
            ansy = 0;
            //memset(vis, 0, sizeof(vis));
            for (int i = 1; i <= n; i++)
                for (int j = 1; j <= m; j++)
                    vis[i][j] = a[i][j] = 0;
            //memset(a, 0, sizeof(a));
            for (int i = 1; i <= A; i++)
            {
                int x, y;
                scanf("%d%d", &x, &y);
                a[x][y] = 1;
            }
            for (int i = 1; i <= B; i++)
            {
                int x, y;
                scanf("%d%d", &x, &y);
                a[x][y] = 2;
            }
            solve1();
            if (ansx == n && ansy == m + 1)
            {
                printf("0
    ");
                continue;
            }
            solve2();
            if (cnt == 0)
            {
                printf("-1
    ");
                continue;
            }
            sort(e + 1, e + 1 + cnt, cmp);
            printf("%d %d %d
    ", cnt, e[1].x, e[1].y);
        }
    
        return 0;
    }

    std:

    #include<cstdio>
    #include<set>
    #include<vector>
    #include<algorithm>
    using namespace std;
    #define rep(i,n) for (int i=0;i<n;++i)
    #define pb push_back
    #define mk make_pair
    #define X first
    #define Y second
    #define tree int t,int l,int r
    #define left t*2,l,mid
    #define right t*2+1,mid+1,r
    #define M int mid=l+r>>1
    const int N=1000005;
    typedef pair<int,int> pr;
    typedef vector<pair<int,pr> > seq;
    set<pr> a[N],b[N]; seq f1,g1,f2,g2; int Case,n,m,R,C,x,y,ll,rr,c[N]; long long ans;
    int get(int x){int res=0; for (;x;x-=x&-x) res+=c[x]; return res;}
    void add(int x,int v){for (;x<=C;x+=x&-x) c[x]+=v;}
    void ins(int side){scanf("%d%d",&x,&y),a[x].insert(mk(y,side)),b[y].insert(mk(x,side));}
    bool track(int x,int y,int d,seq &f,seq &g)
    {
        f.clear(),g.clear(); set<pr> :: iterator it;
        for (;;){
            if (d&1){
                if (d==1){
                    it=b[y].upper_bound(mk(x,1)); f.pb(mk(x+1,mk(y,1)));
                    if (it==b[y].end()) return f.pb(mk(R+1,mk(y,-1))),0;
                    f.pb(mk(it->X,mk(y,-1))),x=it->X,d=it->Y?2:0;
                }else{
                    it=b[y].lower_bound(mk(x,0)); f.pb(mk(x,mk(y,-1)));
                    if (it==b[y].begin()) return f.pb(mk(1,mk(y,1))),0; --it;
                    f.pb(mk(it->X+1,mk(y,1))),x=it->X,d=it->Y?0:2;
                }
            }else{
                if (d==0){
                    it=a[x].upper_bound(mk(y,1));
                    if (it==a[x].end()) return g.pb(mk(x,mk(y+1,C))),x==R;
                    g.pb(mk(x,mk(y+1,it->X-1))),y=it->X,d=it->Y?3:1;
                }else{
                    it=a[x].lower_bound(mk(y,0));
                    if (it==a[x].begin()) return g.pb(mk(x,mk(1,y-1))),0; --it;
                    g.pb(mk(x,mk(it->X+1,y-1))),y=it->X,d=it->Y?1:3;
                }
            }
        }
    }
    void work(seq &f,seq &g)
    {
        sort(f.begin(),f.end()),sort(g.begin(),g.end());
        int m=f.size(),n=g.size(),j=0;
        rep(i,n){
            while (j<m && f[j].X<=g[i].X) add(f[j].Y.X,f[j].Y.Y),++j;
            ll=g[i].Y.X,rr=g[i].Y.Y; int res=get(rr)-get(ll-1); ans+=res;
            if (g[i].X<x && res){
                x=g[i].X,y=ll;
                for (int j=20;j>=0;--j)
                    if (y+(1<<j)<=rr && !(get(y-1+(1<<j))-get(y-1))) y+=1<<j;
                }
            }
        while (j<m) add(f[j].Y.X,f[j].Y.Y),++j;
    }
    int main()
    {
        freopen("safe.in", "r", stdin);
        freopen("safe.out", "w", stdout);
        
        while (scanf("%d%d%d%d",&R,&C,&n,&m)!=EOF){
            rep(i,R+1) a[i].clear(); rep(j,C+1) b[j].clear();
            rep(i,n+m) ins(i<n);
            if (track(1,0,0,f1,g1)){puts("0"); continue;} track(R,C+1,2,f2,g2);
            ans=0,x=R+1,work(f1,g2),work(f2,g1);
            if (ans) printf("%lld %d %d
    ",ans,x,y); else puts("-1");
        }
        return 0;
    }
  • 相关阅读:
    vim tab转换成space
    vs计算项目代码总行数
    读取xml文件
    复选框全选、取消全选
    网页上用js禁用鼠标右键
    腾讯、微软、亚马逊测试站点
    限制文本域输入字符个数,即使显示输入字符数和剩余字符数,超出不显示!
    DataUtil
    DES加密解密类
    JsonHelper(Json帮助类)
  • 原文地址:https://www.cnblogs.com/zbtrs/p/7728477.html
Copyright © 2011-2022 走看看