hdu 5330 Route Statistics 2015多校联合训练赛4 状态压缩

 

Route Statistics

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 66    Accepted Submission(s): 22


Problem Description
JRY is so rich that he creates an  m  demensional space and  n  sight spots inside. Because of special technical problem, all the coordinates are integers between  [0,2] . The roads in this space are all parallel to the axis, so the distance between two sight spots is their Manhattan distance. More specifically, if the coordinate of one sight spot is  (x1,x2,,xm) , and that of another sight spot is  (y1,y2,,ym) , then their distance is  mi=1|xiyi| . JRY wants to establish some bus routes between two sight spots, so he needs to do some research first. For you, the problem is to find the total number of pairs  (x,y)  for each  k , that the distance between (x,y)  is  k . Please be aware: 1.  (x,x)  does not count; 2.  (x,y)  and  (y,x)  are identical, so that it is only one pair; 3. different sight spots may have same coordinates. 
 

Input
The first line of the input is a single integer  T (T=11) , indicating the number of testcases. 

For each testcase, the first line contains two integers  n  and  m . Each of the following  n  lines contains one string of length  m , which consists three types of characters  0,1,2 , and the  j -th character of the  i -th string means the  j -th coordinate of the  i -th spot. It is guaranteed that the  m  of the  i -th testcase is  i , and for all testcases  n300000 .
 

Output
For each testcase, print  2m+1  lines. The single number in the  i -th line of the output indicates the number of pairs of sight spots with distance  i1
 

Sample Input
       
       
       
       
2 2 1 0 1 6 2 00 01 10 11 02 00
 

Sample Output
       
       
       
       
0 1 0 1 7 6 1 0
 

Author
XJZX
 

Source
2015 Multi-University Training Contest 4


http://s14.sinaimg.cn/large/006aTddvgy6Uf9ckC0B7d&690


这个算出来的是离某个点的距离为k的个数。不是最后答案。处理出dp后要对每个点算出离该点距离的为k的个数的累加和。

因为同一个位置可能有多个点。


#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<vector>
using namespace std;
int pow3[20];
int dp[2][200000][24];
char w[12];
long long ans[100];
int num[200000];
int main(){
    pow3[0] = 1;
    for(int i = 1;i <= 11; i++)
        pow3[i] = pow3[i-1]*3;
    int t,m,n;
    scanf("%d",&t);
    for(int tt = 1; tt <= t; tt++){
        memset(dp,0,sizeof(dp));
        memset(num,0,sizeof(num));
        scanf("%d%d",&n,&m);
        for(int i = 0;i < n; i++){
            scanf("%s",w);
            int u = 0;
            for(int j = 0;j < m; j++){
                u = u*3+w[j]-'0';
            }
            dp[0][u][0]++;
            num[u]++;
        }
        int p = 0, q = 1,s0,s1,s2;
        for(int mm=1;mm<=m;mm++){
            memset(dp[q],0,sizeof(dp[q]));
            for(int i = 0;i < pow3[mm-1];i++){
                for(int j = 0;j < pow3[m-mm];j++){
                    for(int d = 0; d <= 2*m;d++){
                        s0 = i+j*pow3[mm];
                        s1 = s0 + pow3[mm-1];
                        s2 = s1 + pow3[mm-1];
                        dp[q][s0][d] += dp[p][s0][d];
                        dp[q][s1][d] += dp[p][s1][d];
                        dp[q][s2][d] += dp[p][s2][d];
                        if(d > 0){
                            dp[q][s0][d] += dp[p][s1][d-1];
                            dp[q][s1][d] += dp[p][s0][d-1];
                            dp[q][s1][d] += dp[p][s2][d-1];
                            dp[q][s2][d] += dp[p][s1][d-1];
                        }
                        if(d > 1){
                            dp[q][s0][d] += dp[p][s2][d-2];
                            dp[q][s2][d] += dp[p][s0][d-2];
                        }
                    }
                }
            }
            swap(p,q);
        }
        memset(ans,0,sizeof(ans));
        for(int i = 0;i < pow3[m]; i++){
            ans[0] += 1ll*num[i]*(num[i]-1);
            for(int j = 1 ;j <= 2*m; j++)
                ans[j] += 1ll*num[i]*dp[p][i][j];
        }
        for(int i = 0;i <= 2*m; i++)
            printf("%I64d\n",ans[i]/2);
    }
    return 0;
}

 





你可能感兴趣的:(HDU,HDU,2015多校联合训练赛,5330)