Time Limit: 2000MS | Memory Limit: 65536K | |
Total Submissions: 3884 | Accepted: 1136 |
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
大意:打地鼠游戏,开始给你的3个数n,d,m分别表示地图大小,每次玩家最多能够移动到的距离,m表示会出现的鼹鼠的个数。
然后问你最多能打掉多少只鼹鼠。
思路:不难想状态转移方程dp[i][j][t]表示点(i,j)在t秒钟之后能够得到的最大分数。
则dp[i][j][t]=max(所有能够全部1步到达点(i,j)的点+路径上在t秒钟出现的鼹鼠的个数)。
注意:这里玩家是可以把手移动到地图外的!!!确实被坑了好久,一开始觉得在外面也没什么卵用啊,但是仔细想了好久,发现玩家只能直线移动,而且必定会落到整数的点的位置上!!!这样就不一样啦。
就像橙色的这个点这样,而横线下面区域在矩阵里的已经都不是整数点了。
所以更新的点数就会变少。
所以把地图外围都扩大5个格。
在枚举路径的时候,因为只能走整数点的格,并且只能走直线所以直接枚举每个能一步到达的点,就是确定了一条直线然后不断直线上的点,确保在范围内就可以了。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAXN=20+20;
int dp[MAXN][MAXN][20];
bool vis[MAXN][MAXN][20];
int n,d,m;
void updata(int x,int y,int t)
{
int l=max(0,x-d),r=min(n-1,x+d);
int s=max(0,y-d),e=min(n-1,y+d);
for(int i=l;i<=r;++i)
for(int j=s;j<=e;++j)
{
if(i==x&&j==y)continue;
int dx=i-x;
int dy=j-y;
int sum=0;
for(int k=0;;++k)
{
int nx=x+k*dx;
int ny=y+k*dy;
if(k*k*(dx*dx+dy*dy)>d*d)break;
if(nx>=n||nx<0||ny>=n||ny<0)break;
if(vis[nx][ny][t])sum++;
dp[x][y][t]=max(dp[x][y][t],dp[nx][ny][t-1]+sum);
}
}
}
int main()
{
int i,j,k;
while(~scanf("%d%d%d",&n,&d,&m))
{
if(!n&&!m&&!d)break;
memset(vis,0,sizeof(vis));
memset(dp,0,sizeof(dp));
int x,y,t;
int ans=0,maxt=0;
while(m--)
{
scanf("%d%d%d",&x,&y,&t);
vis[x+5][y+5][t]=1;
maxt=max(maxt,t);
}
n+=12;
for(k=1;k<=maxt;++k)
for(i=0;i<n;++i)
for(j=0;j<n;++j)
{
updata(i,j,k);
ans=max(ans,dp[i][j][k]);
}
printf("%d\n",ans);
}
return 0;
}