HDU - 6229 Wandering Robots

传送门:点击打开链接

题意:有一个n*n的区域,左上角坐标为(0,0),在左上角有一个机器人,他每次留在原地和前往其他可前往的格子的概率相等,最后若干时间之后,求机器人最后在(x,y)(x+y>=n-1)的点的概率是多少。

分析: 给每个点赋一个权值,权值的大小就代表当前点可以被几个点所到达(包括自身),4个角落的点的权值为3,边缘除角落的权值为4,其余点权值为5,分母就是所有点的权值和,分子是所有终点的权值和。因为n=10000,所以不能暴力,但是因为障碍最多只有1000个,所以我们可以用map或者set把所有的障碍事先存起来。之后对于这些点枚举,用总贡献减去这些点的贡献即可。注意可以需要注意障碍点到达障碍点不需要减,我们需要set标记判断。注意n=1特判。

补充:C++中,结构体是无法进行==,>,<,>=,<=,!=,需要重载,=不需要重载,set内部元素会自动排序,所以set<结构体>需要重载<。

我的代码:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<cstdlib>
#include<ctime>
#include<set>
#include<map>
#include<stack>
#include<queue>
using namespace std;
const int N = 1e4+10;
#define ll long long
#define pb push_back
#define inf 0x3f3f3f3f
#define eps 1e-10
ll t,n,k,fz,fm;
int to[4][2]={-1,0,1,0,0,-1,0,1};

struct br{
    ll x,y;
    bool operator==(const br &a) {///重载==
        return (x==a.x)&&(y==a.y);
    }
    bool operator < (const br a) const {///重载<
        if(x==a.x) return y<a.y;
        return x<a.x;
    }
}b[N];
set<br> st;

ll gcd(ll a,ll b) {
    if(b==0) return a;
    else return gcd(b,a%b);
}

ll gv(ll x,ll y) {
    ll s=5;
    if(x==0||x==n-1) s--;
    if(y==0||y==n-1) s--;
    return s;
}

void sv() {
    fz=9+8*(n-2)+5*(n-1)*(n-2)/2;
    fm=12+16*(n-2)+5*(n-2)*(n-2);
    for(int i=0;i<k;i++) {
        fm-=gv(b[i].x,b[i].y);
        if(b[i].x+b[i].y>=n-1) fz-=gv(b[i].x,b[i].y);
        for(int j=0;j<4;j++) {
            ll xx=b[i].x+to[j][0],yy=b[i].y+to[j][1];
            if(xx<0||xx>=n||yy<0||yy>=n||st.count({xx,yy})) continue;
            fm--;
            if(xx+yy>=n-1) fz--;
        }
    }
    ll tp=gcd(fz,fm);
    fz/=tp,fm/=tp;
    cout<<fz<<"/"<<fm<<endl;
    st.clear();
}

int main() {
    ios::sync_with_stdio(0);
    cin>>t;
    for(int l=1;l<=t;l++){
        cin>>n>>k;
        for(int i=0;i<k;i++) cin>>b[i].x>>b[i].y,st.insert({b[i].x,b[i].y});
        cout<<"Case #"<<l<<": ";
        if(n==1) {
            if(k==1) cout<<"0"<<endl;
            else cout<<"1"<<endl;
        }else sv();
    }
    return 0;
}

参考代码:

#include<bits/stdc++.h>  
using namespace std;  
typedef long long ll;  
const int maxn=2e5+5;  
int dx[4]={0,1,0,-1};  
int dy[4]={1,0,-1,0};  
int n,m,p,q;  
map<pair<int,int>,int> ma;  
int check(int x,int y)  //判断当前点的贡献  
{  
    if((x==0||x==n-1)&&(y==0||y==n-1))  return 3;  
    if((x==0||x==n-1)&&(y!=0&&y!=n-1))  return 4;  
    if((y==0||y==n-1)&&(x!=0&&x!=n-1))  return 4;  
    return 5;  
}  
int main()  
{  
    int QAQ,kase=0;  
    scanf("%d",&QAQ);  
    while(QAQ--)  
    {  
        ma.clear();p=0,q=0;  
        scanf("%d%d",&n,&m);  
        while(m--)  
        {  
            int x,y;  
            scanf("%d%d",&x,&y);  
            ma[make_pair(x,y)]=1;  
        }  
        if(n==1)    //n==1 特判  
        {  
            if(m==1) printf("0\n");  
            else printf("1");  
        }  
        else  
        {  
            q+=((3*4)+((n-2)*4*4)+(n-2)*(n-2)*5);   //分母  
            p+=((3*3)+((n-2)*2*4)+((n-2)*(n-1)/2*5));   //分子  
            for(auto it=ma.begin();it!=ma.end();it++)   //遍历所有障碍  
            {  
                int x=it->first.first;  
                int y=it->first.second;  
                q-=check(x,y);  //减去对分母的贡献  
                if(x+y>=n-1) p-=check(x,y);     //减去对分子的贡献  
                for(int i=0;i<4;i++)    //判断对周围点的贡献的影响  
                {  
                    int xx=x+dx[i];  
                    int yy=y+dy[i];  
                    if(xx>=0&&xx<n&&yy>=0&&yy<n&&ma.count(make_pair(xx,yy))==0)  
                    {  
                        if(xx+yy>=n-1) p--;  
                        q--;  
                    }  
                }  
            }  
            int gk=__gcd(p,q);  //化简  
            printf("Case #%d: %d/%d\n",++kase,p/gk,q/gk);  
        }  
    }  
    system("pause");  
} 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值