【POJ 3034】 Whac-a-Mole(DP)

【POJ 3034】 Whac-a-Mole(DP)

Time Limit: 2000MS   Memory Limit: 65536K
Total Submissions: 3621   Accepted: 1070

Description

While visiting a traveling fun fair you suddenly have an urge to break the high score in the Whac-a-Mole game. The goal of the Whac-a-Mole game is to… well… whack moles. With a hammer. To make the job easier you have first consulted the fortune teller and now you know the exact appearance patterns of the moles.

The moles appear out of holes occupying the n2 integer points (x, y) satisfying 0 ≤ x, y < n in a two-dimensional coordinate system. At each time step, some moles will appear and then disappear again before the next time step. After the moles appear but before they disappear, you are able to move your hammer in a straight line to any position (x2, y2) that is at distance at most d from your current position (x1, y1). For simplicity, we assume that you can only move your hammer to a point having integer coordinates. A mole is whacked if the center of the hole it appears out of is located on the line between (x1, y1) and (x2, y2) (including the two endpoints). Every mole whacked earns you a point. When the game starts, before the first time step, you are able to place your hammer anywhere you see fit.

Input

The input consists of several test cases. Each test case starts with a line containing three integers n, d and m, where n and d are as described above, and m is the total number of moles that will appear (1 ≤ n ≤ 20, 1 ≤ d ≤ 5, and 1 ≤ m ≤ 1000). Then follow m lines, each containing three integers x, y and t giving the position and time of the appearance of a mole (0 ≤ x, y < n and 1 ≤ t ≤ 10). No two moles will appear at the same place at the same time.

The input is ended with a test case where n = d = m = 0. This case should not be processed.

Output

For each test case output a single line containing a single integer, the maximum possible score achievable.

Sample Input

4 2 6
0 0 1
3 1 3
0 1 2
0 2 2
1 0 2
2 0 2
5 4 3
0 0 1
1 2 1
2 4 1
0 0 0

Sample Output

4
2

Source

Nordic 2006


……憋了三天终于憋出来了= =
题目大意:打地鼠……没玩过应该也都见过,地鼠机每秒会有几个洞钻出来地鼠,打中越多分数越高。
先给出n d m三个数,分别表示地鼠机大小(n*n的矩阵,点为洞) 玩家能移动的最远距离d这个下面再解释 地鼠数量m
m个地鼠的给出方式为 x y t
表示第i只地鼠在第t秒从x,y洞钻出。
规则是这样:每次可以从x1,y1移动到x2,y2,要求保证两点间 直线距离小于等于d
移动的路线上所有在该秒钻出的地鼠都会被打中。
在第一秒前,锤子可以在任意位置,之后第i秒只能由i-1秒结束时所在位置开始移动

换言之,就是找一个t秒的路径,能满足路径上打到的地鼠数量最多。

前方高能,直接上思路了,只是来求个题意的话就到这里把
————————————————————————————
————————————————————————————
————————————————————————————
————————————————————————————
————————————————————————————
————————————————————————————
————————————————————————————
————————————————————————————
————————————————————————————
————————————————————————————
————————————————————————————
————————————————————————————


做法dp,枚举秒和该秒锤子的起点,然后由该起点为圆心,
d为半径,那么这个圆内的所有点都可以在该秒从这个点到达
画圆的话代码不太好写,可以换种方式
遍历所有与这个点横坐标距离d内还有纵坐标距离d内的点,判断如果超出范围,就跳出
因为这样遍历只会越遍历越远。

然后一个很坑很坑很坑很坑的地方……


, you are able to move your hammer in a straight line to any position ( x 2, y 2)

move your hammer in a straight line to any position

in a straight line to any position

to any position


any position


any



好了,如果wa的话就去做吧……

附一组数据:

20 5 4
1 0 1
0 1 1
0 5 2
1 6 2
(DISCUSS借的


PS:不光可以负向超出 正向也可以超过n!!!

处理方式就是把0~n移动到5~n+5

然后0~5表示-5~0 n+5~n+10表示正向爆出


代码如下:

#include <iostream>
#include <cmath>
#include <vector>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <queue>
#include <stack>
#include <list>
#include <algorithm>
#include <map>
#include <set>
#define LL long long
#define Pr pair<int,int>
#define fread() freopen("in.in","r",stdin)
#define fwrite() freopen("out.out","w",stdout)

using namespace std;
const int INF = 0x3f3f3f3f;
const int msz = 10000;
const int mod = 1e9+7;
const double eps = 1e-8;

int mp[12][33][33];
int dp[12][33][33];
int tmp[33][33];
int dirx[] = { 1, 1,-1,-1};
int diry[] = { 1,-1, 1,-1};
int d,n;

int dis(int x1,int y1,int x2,int y2)
{
	return (x1-x2)*(x1-x2)+(y1-y2)*(y1-y2);
}

void cal(int t,int x,int y)
{
	int xx,yy;
	for(int i = 0; i <= d; ++i)
		for(int j = 0; j <= d; ++j)
		{
			if(!i && !j)
			{
				dp[t][x][y] += mp[t][x][y];
				tmp[x][y] = dp[t][x][y];
				dp[t+1][x][y] = max(dp[t+1][x][y],dp[t][x][y]);
				//printf("%d:%d,%d %d\n",t,x,y,tmp[x][y]);
				continue;
			}
			if(dis(x,y,x+i,y+j) > d*d) continue;
			for(int k = 0; k < 4; ++k)
			{
				if(!i && dirx[k] < 0) continue;
				xx = x+i*dirx[k];
				if(!j && diry[k] < 0) continue;
				yy = y+j*diry[k];
				if(xx < 0 || xx >= n || yy < 0 || yy >= n) continue;
				int g = __gcd(abs(xx-x),abs(yy-y));
				tmp[xx][yy] = tmp[xx+(x-xx)/g][yy+(y-yy)/g]+mp[t][xx][yy];
				dp[t+1][xx][yy] =  max(dp[t+1][xx][yy],tmp[xx][yy]);
				//printf("%d,%d->%d,%d: %d->%d get:%d\n",x,y,xx,yy,tmp[xx+(x-xx)/g][yy+(y-yy)/g],dp[t+1][xx][yy],mp[t][xx][yy]);
			}
		}
}

int main()
{
	//fread();
	//fwrite();

	int m,x,y,t;
	while(~scanf("%d%d%d",&n,&d,&m) && (n+d+m))
	{
		memset(mp,0,sizeof(mp));
		memset(dp,0,sizeof(dp));
		int tim = 0;
		n += 10;
		while(m--)
		{
			scanf("%d%d%d",&x,&y,&t);
			mp[t][x+5][y+5] = 1;
			tim = max(tim,t);
		}

		for(int i = 1; i <= tim; ++i)
			for(int j = 0; j < n; ++j)
				for(int k = 0; k < n; ++k)
					cal(i,j,k);

		int mx = 0;
		for(int i = 0; i < n; ++i)
			for(int j = 0; j < n; ++j)
				mx = max(mx,dp[tim+1][i][j]);
		printf("%d\n",mx);
	}

	return 0;
}




你可能感兴趣的:(【POJ 3034】 Whac-a-Mole(DP))