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