HDU 5725 Game

来源:互联网 发布:全球云计算大会 上海 编辑:程序博客网 时间:2024/05/16 05:52

Game

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 242    Accepted Submission(s): 45


Problem Description
  Sea5 and wzh are playing games.

  There are some guards on an n × m chessboard. Every guard can attack eight cells around him and release shockwave to attack the whole row and column where he stand.

  Sea5 and wzh are at the beginning stage of the game, they have already put some guards on the chess cells. No guards can be attacked by another guard right now. So they all fell asleep.

  An innocent passer-by is on the chessboard. He can move to up, down, left or right from where he stands. The guards won’t attack him unless the passer-by move to where they stand. The innocent man may appear at any point on the chessboard and move to any point.

  The innocent passer-by wants to know the average shortest distance of all the ways he can move without attacked by guards.
 

Input
  Multiple test cases.

  The first line is an integer T(T50), the number of cases.

  For each case, first line is two integers n and m(2n,m,1000)

  The next n lines contain m symbols indicate the cells of chessboard. ‘G’ indicates a guard and ‘#’ indicates an empty cell.
 

Output
  One line per case, shortest distance of all the ways the passer-by can move without attacked by guards.

  Round the answer to four decimals.
 

Sample Input
12 2##G#
 

Sample Output
0.8889
Hint
Ways of distance 0: 3Ways of distance 1: 4Ways of distance 2: 2The answer is (3 * 0 + 1 * 4 + 2 * 2) / (3 + 4 + 2)

题意:

n*m的图上有一些守卫,守卫的位置,满足彼此不同行,不同列,且相邻8格内不会有其他守卫,现等概率的选取起点和终点,所有可以不碰守卫可以到达的路径中,最短路径的期望。

解题思路:

看了题解才想到怎么写的,首先只要起点和终点不包含守卫的两点都是可达的,而每条路径最多只会背一个守卫阻挡(根据守卫的摆放规则),那么可以先把所有的合法最短路径按曼哈顿距离(即不被阻断的最短距离)计算,然后对于每守卫计算其因阻挡而额外绕行的路线长度(绕行2的距离),最后除以总路线的数目就可以了。
要注意的几点:
(1)n*m的图中任意两点的曼哈顿距离和为n*m*(n*m-1)*(n+m)/3。
(2)读图的时候最好用gets()读会快一些。
(3)要绕行如下:
绕行路线

代码:

#include<iostream>#include<cstdio>#include<cstring>#include<cstdlib>#include<cmath>#include<algorithm>#include<map>#include<string>#include<queue>#include<vector>#include<list>//#pragma comment(linker,"/STACK:1024000000,1024000000")using namespace std;#define INF 0x3f3f3f3fint n,m;long long dp[1005][1005];long long dp2[505][505];char mp[1005][1005];//n*m的图,计算以(1,1)为起点到所有曼哈顿距离和long long get(long long n,long long m){    return m*(m-1)*n/2+n*(n-1)*m/2;}//n*m的图,计算任意点到所有点的曼哈顿距离和long long get2(long long x,long long y){    return get(x,y)+get(n-x+1,y)+get(x,m-y+1)+get(n-x+1,m-y+1)-(get(1,x)+get(1,y)+get(1,n-x+1)+get(1,m-y+1));}int xx[1005],yy[1005],cnt2;int pr[1005],pc[1005];int main(){    int t;    scanf("%d",&t);    while(t--)    {        cnt2=0;        scanf("%d%d",&n,&m);        long long up=(long long)m*n*(m*n-1)*(m+n)/3,down=0;        int cnt=0;        memset(pr,-1,sizeof pr);        memset(pc,-1,sizeof pc);        getchar();        for(int i=0;i<n;i++)        {            gets(mp[i]);            for(int j=0;j<m;j++)            {                if(mp[i][j]=='G')                {                    pr[i]=j;                    pc[j]=i;                    up-=4ll*j*(m-j-1);//同行被阻断会在后面重复计算                    up-=4ll*i*(n-i-1);//同列类似                    up-=2*get2(i+1,j+1),cnt++;                    xx[cnt2]=i;                    yy[cnt2]=j;                    cnt2++;                }            }        }        //计算绕行路径和        int suml=0,sumr=0;        for(int i=0;i<n;i++)        {            if(pr[i]!=-1)            {                if(i==0||pr[i]>pr[i-1]) suml+=pr[i];                else suml=pr[i];                up+=4ll*suml*(m-pr[i]-1);            }            else suml=0;            if(pr[i]!=-1)            {                if(i==0||pr[i]<pr[i-1]) sumr+=m-pr[i]-1;                else sumr=m-pr[i]-1;                up+=4ll*sumr*pr[i];            }            else sumr=0;        }        int sumu=0,sumd=0;        for(int i=0;i<m;i++)        {            if(pc[i]!=-1)            {                if(i==0||pc[i]>pc[i-1]) sumu+=pc[i];                else sumu=pc[i];                up+=4ll*sumu*(n-pc[i]-1);            }            else sumu=0;            if(               pc[i]!=-1)            {                if(i==0||pc[i]<pc[i-1]) sumd+=n-pc[i]-1;                else sumd=n-pc[i]-1;                up+=4ll*sumd*pc[i];            }            else sumd=0;        }        for(int i=0;i<cnt2;i++)        {            for(int j=0;j<cnt2;j++)            {                up+=abs(xx[i]-xx[j])+abs(yy[i]-yy[j]);            }        }        down=(long long)(n*m-cnt)*(n*m-cnt);        double ans=(long double)up/down;        printf("%.4llf\n",ans);    }    return 0;}


1 0
原创粉丝点击