To my boyfriend HDU - 6052 多校第二场

参考:http://blog.csdn.net/calabash_boy/article/details/76272704
题意:题意:给出一个n*m(1<=n,m<=100)的矩阵,每个矩阵元素有一个颜色值ai(0<=ai<=10000),现在定义一个子矩阵的value为子矩阵中不同颜色的数量,求子矩阵value的期望。
所有矩阵可以用组合数求C(n,2)*C(m,2);
然后求每种颜色的贡献;
1
2 3
1 2 1
2 1 2
比如求颜色1时;
枚举1所在的所有位置;
(1,1):包含它的矩阵个数有6个,左边个数右边个数(上边界-下边界+1);
2*3*1=6;
(1,3):不能考虑(1,1) 2*1*2=4;
(2,2):因为不能考虑(1,1),(1,3);所以分两种情况,一种上边界为1,一种为2;
1*3*1+2*2*1=6;
同理枚举2所在位置
8+(3+2)+(2+2);

#include<bits/stdc++.h>  
using namespace std;  
const int MAX = 105;  
int mp[MAX][MAX];  
vector<pair <int,int> > Color[MAX*MAX];  
pair <int,int> now;
int m,n;   
void input(){  
    for (int i=0;i<=n*m;i++){  
        Color[i].clear();  
    }   
    scanf("%d%d",&n,&m);  
    for (int i=1;i<=n;i++){  
        for (int j = 1;j<=m;j++){  
            scanf("%d",&mp[i][j]);  
            Color[mp[i][j]].push_back(make_pair(i,j));  
        }  
    }  
    for (int i=0;i<=n*m;i++){  
        if (!Color[i].empty()){  
            sort(Color[i].begin(),Color[i].end());  
        }  
    }  
}  
vector<int> yIndex[MAX];  
int bottom[MAX];  
long long calc(int col)
{  
//cout<<"Calcing "<<col<<endl;  
    memset(bottom,0,sizeof(bottom));  
    for (int i = 1;i<=n;i++){  
        yIndex[i].clear();  
    }  
    long long ans = 0;  
    for (int i=0;i<Color[col].size();i++){
        now=Color[col][i];
        int ni = now.first,nj = now.second;  
//cout<<"Looping "<<ni<<","<<nj<<endl;  
        for (int i = 1;i<=m;i++){  
            yIndex[i].clear();  
        }  
        for (int i = 1;i<=m;i++){  
            if (bottom[i]){  
                yIndex[bottom[i]].push_back(i);  
            }  
        }  
        int yl=1,yr=m;  
        bool br = false;  
        for (int ii = ni;ii>=1;ii--){  
//cout<<"Findind "<<ii<<endl;  
            for (vector<int>::iterator it = yIndex[ii].begin();it!=yIndex[ii].end();it++){  
                int yy = *it;  
                if (yy<nj){  
                    yl = max(yl,yy+1);  
                }else if (yy>nj){  
                    yr = min (yr,yy-1);  
                }else{  
                    br = true;  
                    break;  
                }  
            }  
            if (br){  
                break;  
//cout<<"Finding Break"<<endl;  
            }  
            ans+=(n-ni+1)*(nj-yl+1)*(yr-nj+1);  
//cout<<"Finding End:With"<<(n-ii+1)*(nj-yl+1)*(yr-nj+1)<<endl;  
        }  
        bottom[nj] = ni;  
    }  

    return ans;  
}  
double work(){  
    long long ans  = 0;  
    for (int i = 0;i<=n*m;i++){  
        if (!Color[i].empty()){  
            ans +=calc(i);  
        }  
    }  
    long long num = n*(n+1)*m*(m+1)/4;//多谢UFO___给我提出的改进建议  
//  for (int i=1;i<=n;i++){  
//      for (int j = 1;j<=m;j++){  
//          num+=i*j;  
//      }  
//  }  
    double anss = ((double)ans)/num;  
//  cout<<"ANS:"<<ans<<" NUM:"<<num<<" Return:"<<anss<<endl;  
    return anss;  
}  
int main(){  
    int Cas;  
    scanf("%d",&Cas);  
    while (Cas--){  
        input();  
        printf("%.9f\n",work());   
    }   
    return 0;  
}  

这里写图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值