dp

先自己写了一个。。 n次WA后搞成TLE~ 。。。  忍无可忍。。 后来参考了网上的代码。 最终AC~

先贴人家的代码吧~

【转】

思路:DP。改了要一天,很纠结的一道题。DP部分,dp[t][x][y]表示第t时间把锤子停在(x,y)上最多能够打到的地鼠数量。则dp[t][x][y] = max(dp[t-1][xx][yy] + (xx,yy)到点(x,y)新打的地鼠数),(xx,yy)和(x,y)的直线距离<d。但是最主要的是下面两点:

1:中转点可能在区域外,如下数据:    //相当重要!!!

20 5 4
1 0 1
0 1 1
0 5 2
1 6 2
答案应该是4而不是3,这就需要扩展区域为n+2d就够啦。

2:(xx,yy)到点(x,y)新打的地鼠数的求法。这点纠结了很久,若一个点在线段(xx,yy)(x,y)上,则这一点上面的地鼠也会被打到。还是看代码吧....

 

源代码:(464K,563MS)

#include<iostream>
#include<cmath>
#include<algorithm>
#define max(a,b) ((a)>(b)?(a):(b))
using namespace std;

 

struct data{
    int dx, dy, dw;
}ste[100];
int n, N, d, m, k;
int dp[15][50][50];
int map[15][50][50];

 

bool cmp(data a, data b){
    return a.dw < b.dw;
}

 

bool inMap(int x, int y){
    if(x >= 0 && x <= N && y >= 0 && y <= N) return true;
    return false;
}

 

int gcd(int a, int b){    //最大公因数
    if(b == 0)  return a;
    return gcd(b, a%b);
}

 

int getSum(int t, int x, int y, int xx, int yy, int dx, int dy){
    int sum = 0;
    do{
        x += dx, y += dy;
        sum += map[t][x][y];
    }while(!(x == xx && y == yy));
    return sum;
}

 

int main(){
    int t, i, T, sum;
    int x, y, xx, yy, dx, dy;
    for(k = 0, x = -5; x <= 5; x ++)    //  先预处理5步内所有可能的走法。(d<=5)
        for(y = -5; y <= 5; y ++)
            if(x*x + y*y <= 25){
                ste[k].dx = x;
                ste[k].dy = y;
                ste[k ++].dw = ceil(sqrt(0.0+x*x+y*y));
            }
    sort(ste, ste+k, cmp);
    while(scanf("%d%d%d", &n, &d, &m) && n){
        memset(dp, 0, sizeof(dp));
        memset(map, 0, sizeof(map));
        T = -1;
        while(m --){
            scanf("%d%d%d", &x, &y, &t);
            map[t][x+d][y+d] = 1;
            T = max(T, t);
        }
        T ++, N = n+2*d;   //   扩展区域。
        for(t = 1; t < T; t ++)
            for(x = 0; x <= N; x ++)
                for(y = 0; y <= N; y ++)
                    for(i = 0; ste[i].dw <= d && i < k; i ++){
                       

相关文章: