Wandering Robots hdu6229 离散化+思维找规律+bitset标记

Wandering Robots
Time Limit: 16000/8000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 26 Accepted Submission(s): 10

Problem Description
In an attempt to colonize Mars, some scientists were tasked with cleaning the planet. A cleaning robot, Marsba,was build with a huge restricted area in the Mars as a massive N × N square grid with K (K ≤ 1000) impassable barriers. This area are numbered from (0, 0) to (N - 1, N - 1) sequentially from left to right, row by row, where N ≤ 10000. The starting point of Marsba is situated on the top left corner lattice (0, 0). Marsba had instructions to program him with equal probability of remaining in the same lattice or travelling to an adjacent one. (Two lattices are said to be adjacent if they share a common edge.) This meant an equal probability being split equally between remaining in the lattice and the number of available routes. Specifically, for the lattice Marsba located in which has d adjacent lattices without impassable barriers, the probability for Marsba of remaining in the lattice or travelling to any adjacent lattice is \frac{1}{d+1} .
Then, those scientists completely forgot about it.
Many millennia ago, a young man realizes the importance of the cleaning robot, Marsba, at the end of the forgotten.
For further research, he asks you to calculate the probability of Marsba’s location (x, y) satisfying x + y ≥ N - 1.
Let the probability be an irreducible fraction of the form p/q, you should output p and q respectively, with a fraction slash as the separator.

Input
The first line of the input contains an integer t (t ≤ 1000) specifying the number of test cases.
For each case, the first line contains two positive integers N and K. Each of the next K lines contains the coordinate of a barrier.
Note that the starting point (0, 0) has no barrier and all test cases guarantee the connectivity of all lattices free of barriers.

Output
For each case output its label first, then output the probability as an irreducible fraction.

Sample Input

5
3 0
3 1
1 1
3 2
1 1
2 2
3 3
1 1
1 2
2 2
5 4
1 1
1 2
2 3
3 2

Sample Output

Case #1: 2/3
Case #2: 5/8
Case #3: 10/19
Case #4: 7/16
Case #5: 43/71

题意:
有一个机器人 一开始在(0,0)点上,每一步机器人有n种操作,停在原地,走向四周没有障碍物的方格。概率平均分布。 问你无限步后,机器人停留在矩阵右下部的概率是多少。
解题思路:
doc“老师” 一贯的题目风格。 面向样例编程然后找规律。
样例都以分数的形式给出,考虑通过确定每个方块的权值来确定最终概率。
以下为找规律的心路历程(纯属瞎逼逼)
假设无限次后每个方块的概率都一样。 那么周围一圈的方块除四个角只有三种到达方式以外,其他的都有四种到达方式。 中间的方块都有5中方式到达 那么如果没有障碍物 图中各个方块的权值可以表示为

344443
455554
455554
455554
455554
344443

然后过了第一个样例
然后考虑有障碍物的情况
猜测每个方块对图的影响是独立的,既可以单独减去这个方块对图的影响。
然后再对了下后面几个样例 发现又对了。 由此找到规律。
自己测了几组样例后发现障碍物围成圈的话 中间的方块权值都会为0(既都看成坏点).
然后观察数据范围 1w*1w的图,但最多只有1000个坏点,可以联想到HDU5925
离散化然后暴力跑一遍离散化后的图 减去每个坏点的贡献即可。
复杂度不知道怎么估算,应该是O(nlogn)级别的。

#include<iostream>
#include<queue>
#include<cstdio>
#include<cmath>
#include<vector>
#include<bitset>
#include<algorithm>
using namespace std;
typedef long long ll;
ll __gcd(ll a, ll b) {
    if(b == 0) return a;
    return __gcd(b,a%b);
}

const int MAX=1e6+10;
int totx=0,toty=0;
int n,k;
int dirx[4]= {1,0,-1,0};
int diry[4]= {0,1,0,-1};
bitset <4000>vis[4000];
bitset <4000>flag[4000];
int hashx[MAX],hashy[MAX];
class point {
public:
    int x,y;
    point(int x,int y):x(x),y(y) {}
};
int getid(int id[],int v,int len) {
    return lower_bound(id,id+len,v)-id;
}
vector<point> V;
long long fm,fz;
void bfs() {
    queue<point> que;
    que.push(point(0,0));
    flag[0][0] = 1;
    while(que.size()) {
        point e = que.front();
        que.pop();
        for(int i = 0; i < 4; i++) {
            int xx = e.x+dirx[i], yy = e.y+diry[i];
            if(xx < 0 || xx >= totx || yy < 0 || yy >= toty || vis[xx][yy] || flag[xx][yy]) continue;
            flag[xx][yy] = 1;
            que.push(point(xx,yy));
        }
    }
}
int main() {
    //freopen("input.txt","r",stdin);
    int cases=0;
    int T;
    scanf("%d",&T);
    while(T--) {
        V.clear();
        totx=0,toty=0;
        scanf("%d %d",&n,&k);
        for(int i=0; i<k; i++) {
            int x,y;
            scanf("%d %d",&x,&y);
            hashx[totx++]=x;
            hashy[toty++]=y;
            if(x-1>=0) hashx[totx++]=x-1;
            if(x+1<n) hashx[totx++]=x+1;
            if(y-1>=0) hashy[toty++]=y-1;
            if(y+1<n) hashy[toty++]=y+1;
            V.push_back(point(x,y));
        }
        hashx[totx++]=0;
        hashy[toty++]=0;
        hashx[totx++]=n-1;
        hashy[toty++]=n-1;
        if(n==1) {
            printf("1/1\n");
            continue;
        }
        for(int i=0; i<=3*k+4; i++) flag[i]&=0,vis[i]&=0;
        sort(hashx,hashx+totx);
        sort(hashy,hashy+toty);
        totx=unique(hashx,hashx+totx)-hashx;
        toty=unique(hashy,hashy+toty)-hashy;
        int cntx,cnty;
        for(int i=0; i<k; i++) {
            cntx=getid(hashx,V[i].x,totx);
            cnty=getid(hashy,V[i].y,toty);
            vis[cntx][cnty]=1;
        }
        fm=12+(4*(n-2)*4)+(n-2)*(n-2)*5;
        fz=9+(2*(n-2)*4)+(n-1)*(n-2)/2*5;
        bfs();
        int ncntx,ncnty;
        for(int i=0; i<totx; i++) {
            for(int j=0; j<toty; j++) {
                if(flag[i][j]==0) {
                    fm--;
                    cntx=hashx[i],cnty=hashy[j];
                    if(cntx+cnty>=n-1)
                        fz--;
                    for(int k=0; k<4; k++) {
                        int nx=i+dirx[k],ny=j+diry[k];
                        if(nx<0 || nx>=totx || ny<0 || ny>=toty) continue ;
                        if(flag[nx][ny]==0) {
                            fm--;
                            if(cntx+cnty>=n-1)
                                fz--;
                        } else {
                            fm-=2;
                            if(cntx+cnty>=n-1)
                                fz--;
                            int ncntx=hashx[nx],ncnty=hashy[ny];
                            if(ncntx+ncnty>=n-1)
                                fz--;
                        }
                    }
                }
            }
        }
        long long gcd=__gcd(fz,fm);
        printf("Case #%d: ",++cases);
        printf("%lld/%lld\n",fz/gcd,fm/gcd);
    }
    //cout<<fz<<"/"<<fm<<endl;

    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值