zoukankan      html  css  js  c++  java
  • 【51Nod】1920 空间统计学 状压DP

    【题目】1920 空间统计学
    【题意】给定m维空间中的n个点坐标,满足每一维坐标大小都在[0,3]之间,现在对于[0,3*m]的每个数字x统计曼哈顿距离为x的有序点对数。(n leq 2*10^5,m leq 9)
    【算法】状压DP
    m范围很小,考虑设计状压DP的状态,可以想到设到达某个坐标j(将m维坐标压成m位四进制数)步数为k(距离等价于步数)的点数,但是难以转移。考虑按维转移,考虑每一维往外走的情况来转移。
    (f_{i,j,k})表示前i维,到达坐标j,步数为k的点数。转移时枚举第i+1维的坐标l,假设坐标j的第i+1维是x,那么:

    $$f(i+1,j+(l-x)*4^i,k+|x-l|)+=f(i,j,k)$$

    最后统计答案的时候,对于每个点坐标j将f[m][j][~]累加进答案即可。
    复杂度(O(m*4^m*3m*4))
    注意:1.时限比较紧,要用读入优化,枚举步数上限3*i等优化常数。2.空间比较紧,要用滚动数组(好像可以不用?)。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    bool isdigit(char c){return c>='0'&&c<='9';}
    int read(){
    	int s=0,t=1;char c;
    	while(!isdigit(c=getchar()))if(c=='-')t=-1;
    	do{s=s*10+c-'0';}while(isdigit(c=getchar()));
    	return s*t;
    }
    using namespace std;
    const int maxn=270010;
    int abs(int x){return x>=0?x:-x;}
    int n,m,f[2][maxn][30],b[10],t[maxn];
    int main(){
    	n=read();m=read();
    	b[0]=1;for(int i=1;i<=m;i++)b[i]=b[i-1]*4;
    	for(int i=1;i<=n;i++){
    		int num=0;
    		for(int j=1;j<=m;j++)num=num*4+read();
    		f[0][num][0]++;//
    		t[i]=num;
    	}
    	int o=0;
    	for(int i=0;i<m;i++){//from 0
    		o=1-o;
    		for(int j=0;j<b[m];j++)for(int k=0;k<=3*(i-1);k++)f[o][j][k]=0;
    		for(int j=0;j<b[m];j++){
    			int x=j/b[i]%4;
    			for(int k=0;k<=3*i;k++)if(f[1-o][j][k])
    				for(int l=0;l<=3;l++)f[o][j+(l-x)*b[i]][k+abs(x-l)]+=f[1-o][j][k];
    		}
    	}
    	for(int k=0;k<=3*m;k++){
    		long long ans=0;
    		for(int j=1;j<=n;j++)ans+=f[o][t[j]][k];
    		printf("%lld ",ans);
    	}
    	return 0;
    }
  • 相关阅读:
    js中的replace替换全部
    Oracle中创建数据链
    Hbuildx+vue+axios+element ui初学部署
    html5抠图
    Oracle误删除数据的恢复方法
    vs 生成项目自动关闭当前运行程序
    Mvc项目在iis上面显示文件夹 输入地址页面也打不开
    FastReport快速打印(.net)
    脚本之家
    VS自定义作者、创建时间
  • 原文地址:https://www.cnblogs.com/onioncyc/p/9084867.html
Copyright © 2011-2022 走看看