http://poj.org/problem?id=3034
n*n方阵 特定时间 特定位置有 moles 同一时间锤子可以 打一条直线上的moles
直线最大距离为 d
根据时间 逐层更新数量
注意超出 d 范围的情况 和 锤子停留在方阵外的情况
代码及其注释:
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<queue>
#include<cmath>
#include<stack>
#include<algorithm>
using namespace std;
int sum[15][42][42];//时间 位置 记录最大值
int appear[15][42][42];//时间 位置 是否出现moles
int d;
int FindSum(int x,int y,int x1,int y1,int t)//在第 t 时间从(x.y)到(x1,y1) 可以多少moles
{
if((x-x1)*(x-x1)+(y-y1)*(y-y1)>d*d)//如果超出范围 返回-1
return -1;
if(y>y1)
{
swap(y,y1);
swap(x,x1);
}
int kx=x1-x;int ky=y1-y;
int s=0;
if(x==x1)
{
for(int j=y;j<=y1;++j)
{
if(appear[t][x][j]==1)
++s;
}
return s;
}
if(y==y1)
{
for(int i=min(x,x1);i<=max(x,x1);++i)
{
if(appear[t][i][y]==1)
++s;
}
return s;
}
if(appear[t][x][y]==1)
++s;
if(appear[t][x1][y1]==1)
++s;
if((abs(kx)==2&&(ky==4||ky==2))||((abs(kx)==2||abs(kx)==4)&&ky==2))
{
if(appear[t][(x+x1)/2][(y+y1)/2]==1)
++s;
return s;
}
if(abs(kx)==3&&ky==3)
{
if((kx==3&&appear[t][x+1][y+1]==1)||(kx==-3&&appear[t][x-1][y+1]==1))
++s;
if((kx==3&&appear[t][x+2][y+2]==1)||(kx==-3&&appear[t][x-2][y+2]==1))
++s;
return s;
}
return s;
}
int main()
{
int n,m;
while(scanf("%d %d %d",&n,&d,&m)!=EOF)
{
if(n==0&&d==0&&m==0)
break;
memset(appear,0,sizeof(appear));
int T=0;
while(m--)
{
int x,y,t;
scanf("%d %d %d",&x,&y,&t);
T=max(T,t);
appear[t][x+d][y+d]=1;
}
memset(sum,0,sizeof(sum));
int ans=0;
for(int t=1,k=1;t<=T;++t,k=k*10)
{
for(int x=0;x<n+2*d;++x)
{
for(int y=0;y<n+2*d;++y)
{
for(int i=0;i<n+2*d;++i)
{
for(int j=0;j<n+2*d;++j)
{
int q=FindSum(x,y,i,j,t);
if(q==-1)//无法到达 不更新
continue;
sum[t+1][i][j]=max(sum[t+1][i][j],sum[t][x][y]+q);//更新
if(t==T)
ans=max(ans,sum[t+1][i][j]);//找最大值
}
}
}
}
}
printf("%d\n",ans);
}
return 0;
}
浙公网安备 33010602011771号