分析:暴力的方法是非常显然的,从起点走一次,从终点走一次,路径相交的点即为所求,但是这样存图都很难存下,而且如果数据极端可能要求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; }