您的位置:首页 > 其它

2017第二次多校联合 hdu6052 tobemyboyfriend

2017-08-01 19:15 393 查看
假装这里有链接

题意:给你一个矩阵,每个格子有种颜色,求任意大小子矩阵的期望。

解:期望=所有子矩阵颜色数和/子矩阵个数。那首先要解决的就是子矩阵个数,如果已知矩阵右下角(i,j),那左边界和上边界一定在(0,0)~(i,j)里,就是i*j。

然后解决所有子矩阵颜色数和,可以求每个颜色包含在多少矩阵里,因为可能会重复,所以自上而下,自左而右考虑。便利每个点,假设便利到(x,y),便利x的左边界(因为自左而右考虑,所以x的右边是不会重复的),x的右边界这时候就是m,左边界就是和x同行的与x的颜色相同的位置,然后便利(x-1)行,寻找左边界右边界,但是要考虑x行的边界,

所以(x-1)行的左边界是≥x行的左边界,同理(x-1)行的右边界是≤x行的右边界的。然后如果便利到了这一行的左右边界LR,那么满足条件的矩阵就是(y-L+1)(R-y+1)(n-x+1)个。

要注意如果x上面恰好有一个已经便利过的与x同色的点S的话,S这一行是不能便利的,这时就结束便利,计算所有矩阵。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn=105;
int co[maxn][maxn];
int n,m;
int solve(int x,int y)
{
ll sum=0;
int c=co[x][y];
int L=1,R=m;
for(int i=x;i>=1;i--)
{
if(i<x&&co[i][y]==c)break;
for(int j=y-1;j>=max(L,1);j--)
{
if(co[i][j]==c)
{
L=max(j+1,L);
break;
}
}
if(i==x)
{
sum += (n - x + 1) * (y - L + 1) * (R - y + 1);
continue;
}
for(int j=y+1;j<=min(m,R);j++)
{
if(co[i][j]==c)
{
R=min(R,j-1);
break;
}
}
sum+=(y-L+1)*(R-y+1)*(n-x+1);
}
return sum;
}
int main()
{
int t;
//freopen("data.in", "r", stdin);
//freopen("data.out", "w", stdout);
scanf("%d",&t);
while(t--)
{
memset(co,0,sizeof co);
scanf("%d %d",&n,&m);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
scanf("%d",&co[i][j]);
}
}
ll sum1=0,sum2=0;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
sum1+=solve(i,j);
sum2+=i*j;
}
}
printf("%.9f\n",sum1*1.0/sum2);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: