poj3034 Whac-a-Mole

该博客讨论了如何解决一个打地鼠游戏的问题,其中玩家需要在给定的地图大小和最大移动距离限制下,计算出能打到的最多鼹鼠数量。博主提出使用动态规划方法来确定每个位置在特定时间后的最大得分,并强调了考虑地图边界条件的重要性,因为玩家只能直线移动到整数坐标。最后,博主分享了解决问题的关键思路和陷阱,即要考虑地图外的范围,因为玩家的移动路径始终落在整数点上。

Whac-a-Mole
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 (xy) satisfying 0 ≤ xy < 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 (x2y2) that is at distance at most d from your current position (x1y1). 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 (x1y1) and (x2y2) (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 nd 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 xy and t giving the position and time of the appearance of a mole (0 ≤ xy < 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;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值