您的位置:首页 > 其它

poj 3034 Whac-a-Mole(dp)

2014-08-15 16:39 435 查看
题目: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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  dp