POJ 3034 简单dp--注意细节

没考虑到锤子可能到达界外一直不过,

从界外也能转移进来,并可能得到更优的结果

想法是简单的,从前一秒的每个状态转移到下一秒的每个状态,状态数比较小,能过

在处理经过时得到几分比较山寨,凑合着吧。。

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


你可能感兴趣的:(POJ 3034 简单dp--注意细节)