poj 3034 Whac-a-Mole(dp)

题目:http://poj.org/problem?id=3034

【题意】就是打鼹鼠游戏。n*n个洞,给出m个鼹鼠开始出现的位置和时间,每个鼹鼠出现的时长为1s。一开始锤子可放在任意位置,每秒移动的距离为0~d(1<=d<=5)

锤子只能直线移动,可以把在线段(包括端点)上的鼹鼠都打掉。锤子放置的位置只能是整数点。

【思路】可以很容易写出状态转移方程  dp[t][i][j]=max(dp[t-1][x][y]+walk(x,y,i,j)),dp[t][i][j]表示的是第t秒后锤子放在(i,j)最多打的鼹鼠,walk(x,y,i,j,t)表示锤子

从(x,y)->(i,j)在第t秒打到的鼹鼠。walk写的很纠结。。一开始想预处理出所有的walk。。发现既不好搞,又没意义。。

注意:锤子可以放在游戏界面之外。。

【代码】

/*
只能说这个题太好了=_=
*/
#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>

using namespace std;
int dp[15][30][30];
int abs(int a)
{
    return a>0?a:-a;
}
int mp[15][30][30];

int gcd(int a,int b)
{
    if(b==0)return a;
    return gcd(b,a%b);
}

int walk(int x,int y,int i,int j,int time)
{
    int cnt=0;
    int dx=i-x,dy=j-y;
    if(dx==0&&dy==0)return mp[time][x][y];
    int g;
    if(dx==0||dy==0)
        g=abs(dx+dy);
    else g=gcd(abs(dx),abs(dy));
    dx=dx/g;dy=dy/g;
    for(int i=0;i<=g;i++)
        cnt+=mp[time][dx*i+x][dy*i+y];
    return cnt;
}

int main()
{
    int n,d,m;
    while(scanf("%d%d%d",&n,&d,&m)!=EOF)
    {
        if(n+d+m==0)break;
        memset(mp,0,sizeof(mp));
        int mtime=0;
        for(int i=0;i<m;i++)
        {
            int x,y,time;
            scanf("%d%d%d",&x,&y,&time);
            mp[time][x+d][y+d]=1;//x+d,y+d处理锤子走直线出游戏界面的情况
            mtime=max(mtime,time);
        }
        memset(dp,0,sizeof(dp));
        n+=2*d;
        //cout<<"f"<<endl;
        for(int t=1;t<=mtime;t++)
            for(int i=0;i<n;i++)
                for(int j=0;j<n;j++)
                {
                   // cout<<"f2"<<endl;
                    int top=max(0,i-d),bot=min(n-1,i+d);
                    int left=max(0,j-d),right=min(n-1,j+d);
                    for(int x=top;x<=bot;x++)
                    {
                        for(int y=left;y<=right;y++)
                        {

                            if((x-i)*(x-i)+(y-j)*(y-j)>d*d)continue;
                            //cout<<"t="<<t<<ends<<x<<ends<<y<<" to "<<i<<ends<<j<<endl;
                            dp[t][i][j]=max(dp[t][i][j],dp[t-1][x][y]+walk(x,y,i,j,t));
                        }
                    }
                }
        int ans=0;
        for(int i=0;i<n;i++)
            for(int j=0;j<n;j++)
                ans=max(ans,dp[mtime][i][j]);
        printf("%d\n",ans);
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值