打地鼠游戏,n*n的矩阵,每一个整数点(x,y)都有一个鼠洞,某个老鼠在某个鼠洞出现的时间只有一秒。游戏者拿着锤子,锤子可以在任意一个整数点上(不一定在矩阵内)。游戏者每一秒可以将锤子从当前位置直线移动到下一位置(整数点)。两位置之间的距离不超过d。移动的直线路径穿过的(过整数点中心的)鼠洞如果有老鼠,都会被打晕。例如(0,0)移动到(0,3)。如果(0,1),(0,2)有老鼠出现就会被打晕。打晕一只老鼠得一分,求最大分数。
解题思路:
Dp[i][j][k]代表点(i,j)在第k秒最多可以得多少分。
它等于dp[x][y][k-1](点(x,y)为任意一个一秒内能到达(i,j)的点。)加上路径中打晕的地鼠数。求他们的最大值。
下面是代码:
#include <stdio.h> #include <string.h> #include <string> #include <iostream> #include <algorithm> #include <vector> #include <math.h> #include <map> #include <queue> #include <stack> #include <set> #define maxn 100005 #define LL long long #define ll __int64 #define eps 1e-4 #define INF 1e8 #define pi acos(-1.0) #define mol 200907 using namespace std; int min(int a,int b) { if(a>b)a=b; return a; } int max(int a,int b) { if(a<b)a=b; return a; } int dp[30][30][15],d,n,m; bool vis[30][30][15]; int does(int x,int y,int t) { int l=0,u=0; if(x-d>l)l=x-d; if(y-d>u)u=y-d; int r=n+10; int e=n+10; if(x+d+1<r)r=x+d+1; if(y+d+1<e)e=y+d+1; int max2=0,xadd,yadd,div,temp; for(;l<r;l++) { for(int ux=u;ux<e;ux++) { if(((l-x)*(l-x)+(ux-y)*(ux-y))<=d*d) { xadd=abs(l-x); yadd=abs(ux-y); div=__gcd(xadd,yadd); if(div!=0) { xadd/=div; yadd/=div; } else if(xadd==0) { yadd=1; } else if(yadd==0) { xadd=1; } if(l>x)xadd=-xadd; if(ux>y)yadd=-yadd; temp=dp[l][ux][t-1]; for(int w=l,h=ux;w!=x||h!=y;w+=xadd,h+=yadd) { if(vis[w][h][t]) { temp++; } } if(vis[x][y][t])temp++; max2=max(max2,temp); } } } return max2; } int main() { while(scanf("%d%d%d",&n,&d,&m),n||d||m) { memset(vis,false,sizeof(vis)); memset(dp,0,sizeof(dp)); int x,y,t; for(int i=0;i<m;i++) { scanf("%d%d%d",&x,&y,&t); vis[x+5][y+5][t]=true; } int max1=0; for(int k=1;k<=10;k++) { for(int i=0;i<n+10;i++) { for(int j=0;j<n+10;j++) { dp[i][j][k]=does(i,j,k); max1=max(max1,dp[i][j][k]); } } } printf("%d\n",max1); } return 0; }