**问题 C: 曼哈顿距离(manhattan)** **时间限制: 2 Sec 内存限制: 512 MB**
**题目描述** 现在我们建立一个n维的直角坐标系,每个点可以用它的坐标$(x_1,x_2,⋯,x_n)$来表示。如果我们设定每一维坐标都必须是不超过m的正整数,那么一共就有$m^n$个点。 对于两个点$(a_1,a_2,⋯,a_n)$与$(b_1,b_2,⋯,b_n)$,我们定义$∑_{i=1}^n |a_i-b_i |$,即$|a_1-b_1 |+|a_2-b_2 |+⋯+|a_n-b_n |$,为这两个点的曼哈顿距离。容易看出,两个点的距离至少为$0$,至多为$n(m-1)$。 $m^n$个点中的每个点都具有一个权值。你需要对于每个点,对于每个满足$0≤ d≤ n(m-1)$的$d$,求出和这个点距离为$d$的所有点的权值之和。(如果不存在这样的点则应输出$0$) **输入** 第一行输入两个正整数$n,m$,用空格隔开。 接下来$m^n$行,每行一个正整数,表示每个点的权值。输入是按照坐标序列的字典序排列的,即先输入点$(1,1,⋯,1,1)$的权值,再输入$(1,1,⋯,1,2)$的权值,……,再输入$(1,1,⋯,1,m)$的权值,再输入$(1,1,⋯,2,1)$的权值…… **输出** 输出$m^n$行,每行表示一个点。每行有$n(m-1)+1$个整数,依次表示和这个点距离为$0,1,⋯,n(m-1)$的所有点的权值之和。 输出的点的顺序应与输入相同;同一行相邻的两个整数之间应当用恰好一个空格隔开。 **样例输入** 2 3 9 8 7 6 5 4 3 2 1 **样例输出** 9 14 15 6 1 8 21 12 4 0 7 12 15 8 3 6 17 14 8 0 5 20 20 0 0 4 13 16 12 0 3 8 15 12 7 2 9 18 16 0 1 6 15 14 9 **提示** ![](https://img-blog.csdn.net/20180829222615800) **题解:** $dp[i][j][k]$前$i$维,第$j$个点,当前距离为$k$ 那dp转移也非常简单,直接枚举相邻的点进行转移 注意第一维要滚动数组,否则会爆空间 **Code:**
#include<cstdio>
#include<algorithm>
#include<cstring>
#define N 1000005
#define M 70005
using namespace std;
int Pow[N],dp[2][M][205],a[N],num[M][105],n,m,x[1010];
int main()
{
scanf("%d%d",&n,&m);
if(n==1)
{
for(int i=1;i<=m;i++)scanf("%d",&x[i]);
for(int i=1;i<=m;i++)
{
for(int j=0;j<m;j++)
{
int ans=0;
if(i>j)ans+=x[i-j];
if(i+j<=m&&j)ans+=x[i+j];
if(j!=m-1)printf("%d ",ans);else
printf("%d\n",ans);
}
}
}else
{
int Q=1;
for(int i=1;i<=n;i++)Q=Q*m;
for(int i=0;i<Q;i++)
{
int now=n,t=i;
for(int j=1;j<=n;j++)num[i][j]=1;
while(t)
{
num[i][now]+=t%m;
t/=m;
now--;
}
scanf("%d",&dp[0][i][0]);
}
Pow[n]=1;
for(int i=n-1;i;i--)Pow[i]=Pow[i+1]*m;
for(int i=1;i<=n;i++)
{
for(int j=0;j<Q;j++)
for(int k=0;k<=n*(m-1);k++)
for(int d=0;d<m;d++)
{
if(k+d>n*(m-1))continue;
if(num[j][i]+d<=m)
dp[i%2][j][k+d]+=dp[(i-1)%2][j+d*Pow[i]][k];
if(num[j][i]-d>0&&d)
dp[i%2][j][k+d]+=dp[(i-1)%2][j-d*Pow[i]][k];
}
for(int j=0;j<Q;j++)
for(int k=0;k<=n*(m-1);k++)
dp[(i-1)%2][j][k]=0;
}
for(int i=0;i<Q;i++)
for(int j=0;j<=n*(m-1);j++)
if(j<n*(m-1))printf("%d ",dp[n%2][i][j]);else
printf("%d\n",dp[n%2][i][j]);
}
return 0;
}