没考虑到锤子可能到达界外一直不过,
从界外也能转移进来,并可能得到更优的结果
想法是简单的,从前一秒的每个状态转移到下一秒的每个状态,状态数比较小,能过
在处理经过时得到几分比较山寨,凑合着吧。。
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <vector>
using namespace std;
#define eps 1e-8
int n,d,m;
int vis[15][33][33];
int dp[15][33][33];
inline int count(int sx,int sy,int ex,int ey,int tm)
{
int ret=0;
if(sx==ex)
{
if(ey<sy)
swap(ey,sy);
for(int j=sy;j<=ey;++j)
if(vis[tm][sx][j])
ret++;
}
else if(sy==ey)
{
if(ex<sx)
swap(ex,sx);
for(int i=sx;i<=ex;++i)
if(vis[tm][i][sy])
ret++;
}
else
{
if(ex<sx)
{
swap(sx,ex);
swap(sy,ey);
}
double r=(ey-sy)*1.0/((ex-sx)*1.0);
for(int i=0;i+sx<=ex;++i)
{
double ty=i*r+1.0*sy;
int inty=ty+eps;
if(vis[tm][sx+i][inty] && (inty-sy)*(ex-sx)==(ey-sy)*i)
ret++;
}
}
return ret;
}
int main ()
{
while(scanf("%d%d%d",&n,&d,&m)!=EOF)
{
if(n==0 && d==0 && m==0) break;
memset(vis,0,sizeof(vis));
memset(dp,0,sizeof(dp));
n+=2*d;
int tot=0;
for(int i=1;i<=m;++i)
{
int x,y,tt;
scanf("%d%d%d",&x,&y,&tt);
vis[tt][x+d][y+d]=1;
tot=max(tot,tt);
}
for(int i=0;i<tot;++i) // from i to i+1
{
for(int x1=0;x1<n;++x1)
for(int y1=0;y1<n;++y1)
{
for(int x2=x1-d;x2<=x1+d;++x2)
for(int y2=y1-d;y2<=y1+d;++y2)
if(x2>=0 && x2<n && y2>=0 && y2<n && (x2-x1)*(x2-x1)+(y2-y1)*(y2-y1)<=d*d)
{
int cnt=count(x1,y1,x2,y2,i+1);
if(dp[i+1][x2][y2]<dp[i][x1][y1]+cnt)
dp[i+1][x2][y2]=dp[i][x1][y1]+cnt;
}
}
}
int ans=0;
for(int i=0;i<n;++i)
for(int j=0;j<n;++j)
ans=max(ans,dp[tot][i][j]);
printf("%d\n",ans);
}
return 0;
}