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


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;
}

 





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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

GDRetop

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值