51nod 1920 空间统计学 动态规划

来源:互联网 发布:淘宝网购物帽子 编辑:程序博客网 时间:2024/06/07 07:09

题意

有个m维的空间,并且每一维的坐标x都满足x∈ [0, 3]并且x为整数。
这个空间有n个部落,每个部落都坐落在这片空间中的一个点上,可以用坐标(x1, x2, …, xm)来表示。
有些部落可能在在同一个点上面。
定义两个点的距离为它们的曼哈顿距离,即每一维坐标差的绝对值的和。
比如对于点(x1, x2, …, xm)和(y1, y2, …, ym),它们之间的距离为
现在对0~3m之间的每一个数字x,统计有多少对部落之间的距离为x。
注意,一对部落是有序的,即部落(a, b)和部落(b, a)为不同的两对。
n<=200000,m<=9

分析

可以设f[i,j,k]表示四进制下前i位和k的距离为j,且后m-i位和k相同的数有多少个。
xjb转移即可。

代码

#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<algorithm>using namespace std;typedef long long LL;int n,m,bin[15],f[10][30][272144];struct data{int a[10];}bel[272144],a[200005];LL ans[30];int read(){    int x=0,f=1;char ch=getchar();    while (ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}    while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}    return x*f;}int get_num(data a){    int ans=0;    for (int i=m;i>=1;i--) ans=ans*4+a.a[i];    return ans;}data get_pos(int x){    data a;    for (int i=1;i<=m;i++) a.a[i]=x%4,x>>=2;    return a;}int main(){    n=read();m=read();    bin[0]=1;    for (int i=1;i<=m;i++) bin[i]=bin[i-1]*4;    for (int i=1;i<=n;i++)    {        for (int j=1;j<=m;j++) a[i].a[j]=read();        int x=get_num(a[i]);        f[0][0][x]++;    }    for (int i=0;i<bin[m];i++) bel[i]=get_pos(i);    for (int i=1;i<=m;i++)        for (int j=0;j<=m*3;j++)            for (int k=0;k<bin[m];k++)            {                int now=bel[k].a[i];                for (int l=0;l<=3;l++) if (j>=abs(l-now)) f[i][j][k]+=f[i-1][j-abs(l-now)][k-bin[i-1]*(now-l)];            }    for (int i=1;i<=n;i++)    {        int x=get_num(a[i]);        for (int j=0;j<=m*3;j++) ans[j]+=f[m][j][x];    }    for (int i=0;i<=m*3;i++) printf("%lld ",ans[i]);    return 0;}
原创粉丝点击