poj3034--Whac-a-Mole(dp)

题目链接:点击打开链接

题目大意:砸地鼠游戏,n*n的方格,锤子每次最多移动d,地鼠在t时刻出如今(x,y)时间。维持一个单位时间,不会在同一时间同一位置出现两仅仅老鼠,锤子能够砸经过的地鼠,问最多能够砸多少地鼠。(初始锤子能够在任何位置)

dp[t][i][j]:t时刻在锤子在(i,j)位置时能砸到的最多的地鼠个数

状态转移方程:由于锤子最多移动d,所以枚举(x-d,y-d)到(x+d,y+d)的点(tx,ty),觉得这是(x,y)向(tx,ty)移动的第一个点。然后计算在d范围内的点。统计被砸的地鼠的个数

注意:肯能通过边界外的点进行移动

20 5 4
1 0 1
0 1 1
0 5 2
1 6 2
0 0 0
结果是4

所以要将全部的点移动(5,5)的距离,能够避免负坐标

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std ;
int dp[12][41][41] ;
int Map[12][41][41] ;
void f(int n,int t,int x,int y,int d) {
    int i , j , k , p , q , num ;
    for(i = max(0,x-d) ; i <= min(n-1,x+d) ; i++) {
        for(j = max(0,y-d) ; j <= min(n-1,y+d) ; j++) {
            if( i == x && j == y ) continue ;
            p = i - x ;
            q = j - y ;
            k = num = 0 ;
            while( x+k*p >= 0 && x+k*p < n && y+k*q >= 0 && y+k*q < n && k*k*(q*q+p*p) <= d*d ) {
                if( Map[t][x+k*p][y+k*q] ) num++ ;
                dp[t][x][y] = max(dp[t][x][y],dp[t-1][x+k*p][y+k*q]+num) ;
                k++ ;
            }
        }
    }
    return ;
}
int main() {
    int n , d , m ;
    int x , y , t ;
    int i , j , max_t , ans ;
    while( scanf("%d %d %d", &n, &d, &m) && n+d+m != 0 ) {
        memset(dp,0,sizeof(dp)) ;
        memset(Map,0,sizeof(Map)) ;
        max_t = ans = 0 ;
        while( m-- ) {
            scanf("%d %d %d", &x, &y, &t) ;
            Map[t][x+5][y+5] = 1 ;
            max_t = max(max_t,t) ;
        }
        n += 12 ;
        for(t = 1 ; t <= max_t ; t++) {
            for(i = 0 ; i < n ; i++) {
                for(j = 0 ; j < n ; j++) {
                    f(n,t,i,j,d) ;
                    ans = max(ans,dp[t][i][j]) ;
                }
            }
        }
        printf("%d
", ans) ;
    }
    return 0 ;
}


原文地址:https://www.cnblogs.com/liguangsunls/p/6791491.html