POJ 3034 DP

打地鼠游戏中,你有一个锤子,每一秒钟你可以拿着锤子移动d个单位的距离,必须是直线,掠过的鼠洞中露出的地鼠都会被锤打至,而事先知道从开始时各时间段内出现在老鼠的数量和位置,问题是从游戏开始至结束时,你最多能打到多少只地鼠,开始时锤子可以在任何位置。

题目有个陷阱,

只是说Moles出现的坐标为正,但没说hammer移动的位置要为正,可以为"any position"

所以锤子可以移出矩阵,再从矩阵外一点移进来

例:

20 5 4

1 0 1

0 1 1

0 5 2

1 6 2

0 0 0

答案应该是:4

把n*n矩阵变为  (n+2d)*(n+2d)的矩阵,所有地鼠的x和y各加d,在这个矩阵内DP。

我们把每一秒看成一个状态,则当前时间下,锤子落在各位置上能打到的最多的地鼠为能在一秒内移动至该位置的各位置到达该位置时打到的地鼠数量与出发状态时快打到的地鼠数量之和的最大值。

#include "stdio.h"
#include "string.h"
#include "stdlib.h"

struct node
{
    int x,y;
}map[11][1010];

int temp[31][31],dp[2][31][31],time[11];

int Max(int a,int b)
{
    if(a<b) return b;else return a;
}
int gcd(int a,int b)
{
    if (b==0) return a; else return gcd(b,a%b);
}
int cal(int x,int y,int tx,int ty) // 记录在某时间从(x,y)走到(tx,ty) 所产生的价值
{
    int dx,dy,tp,ans;
    if (x==tx && y==ty) return temp[x][y];
    dx=tx-x;
    dy=ty-y;
    tp=gcd(abs(dx),abs(dy));
    dx/=tp;
    dy/=tp;

    ans=0;
    for (x,y;x!=tx || y!=ty;x+=dx,y+=dy)
        ans+=temp[x][y];
    ans+=temp[tx][ty];
    return ans;
}
int main()
{
    int n,d,m,x,y,t,i,j,l,ans,a,b;
    while (scanf("%d%d%d",&n,&d,&m)!=EOF)
    {
        if (n+d+m==0) break;
        memset(map,0,sizeof(map));
        memset(time,0,sizeof(time));
        while (m--)
        {
            scanf("%d%d%d",&x,&y,&t);
            time[t]++; //记录时间t一共出现了多少地鼠
            map[t][time[t]].x=x+d; // 记录时间t出现的每一个地鼠
            map[t][time[t]].y=y+d;
        }
        n+=d+d;

        memset(dp,0,sizeof(dp));

        for (i=1;i<=10;i++)
        {
            memset(temp,0,sizeof(temp));
            for (j=1;j<=time[i];j++)
                temp[map[i][j].x][map[i][j].y]=1;// 记录时间i出现的地鼠图
            for (j=0;j<n;j++)
                for (l=0;l<n;l++) // 枚举位置
                {
                    dp[i%2][j][l]=dp[1-i%2][j][l];
                    for (a=-d;a<=d;a++)
                        for (b=-d;b<=d;b++) //枚举移动方式
                        {
                            if (a*a+b*b>d*d) continue;
                            x=a+j;
                            y=b+l;
                            if (x<0 || x>=n || y<0 || y>=n) continue;
                            dp[i%2][j][l]=Max(dp[i%2][j][l],dp[1-i%2][x][y]+cal(x,y,j,l));
                        }
                }
        }
        ans=0;
        for (i=0;i<n;i++)
            for (j=0;j<n;j++)
            ans=Max(ans,dp[0][i][j]);

        printf("%d\n",ans);
    }
    return 0;
}

POJ 3034 DP

时间: 2024-10-02 20:46:13

POJ 3034 DP的相关文章

POJ 3034 Whac-a-Mole(DP)

题目链接 题意 : 在一个二维直角坐标系中,有n×n个洞,每个洞的坐标为(x,y), 0 ≤ x, y < n,给你一把锤子可以打到地鼠,最开始的时候,你可以把锤子放在任何地方,如果你上一秒在(x1,y1),那下一秒直线移动到的整数点(x2,y2)与这个点的距离小于等于d,并且当锤子移动(x2,y2)这个点时,所有在两点的直线上的整点数都可以打到.例如(0,0)移动到(0,3).如果(0,1),(0,2)有老鼠出现就会被打到.求能够打的最多老鼠. 思路 : Dp[i][j][k]代表点(i,j)

【POJ 3034】 Whac-a-Mole(DP)

[POJ 3034] Whac-a-Mole(DP) Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 3621   Accepted: 1070 Description While visiting a traveling fun fair you suddenly have an urge to break the high score in the Whac-a-Mole game. The goal of the W

poj 3034 Whac-a-Mole

http://poj.org/problem?id=3034 题意:打地鼠游戏中,你有一个锤子,每一秒钟你可以拿着锤子移动d个单位的距离,掠过的鼠洞中露出的地鼠都会被锤打至,而事先知道从开始时各时间段内出现在老鼠的数量和位置,问题是从游戏开始至结束时,你最多能打到多少只地鼠,开始时锤子可以在任何位置. 1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 using namespace std

HDU 1087 &amp;&amp; POJ 2533(DP,最长上升子序列).

~~~~ 两道题的意思差不多,HDU上是求最长上升子序列的和,而POJ上就的是其长度. 貌似还有用二分写的nlogn的算法,不过这俩题n^2就可以过嘛.. ~~~~ 题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1087 http://poj.org/problem?id=2533 ~~~~ HDU1087: #include<cstdio> #include<cstring> #include<algorithm> #

POJ 3670 &amp;&amp; POJ 3671 (dp)

最长不下降子序列的应用嘛.两题都是一样的. POJ 3670:求给定序列按递增或递减排列时,所需改变的最小的数字的数目. POJ 3671:求给定序列按递增排列时,所需改变的最小的数字的数目. 思路就是求最长不下降子序列,然后剩下的就是需要改变的字母. 最长不下降子序列:(我之前有写过,不懂请戳)http://blog.csdn.net/darwin_/article/details/38360997 POJ 3670: #include<cstdio> #include<cstring

poj 3783 DP 2个鸡蛋扔100层楼的加强版

http://poj.org/problem?id=3783 估计23号之后的排位赛之后我就要退役了,这之前最后再做5天ACM 今天的排位很惨,上次排位也很惨......这道题原来算法课老师讲过,模模糊糊记得方程,但是边界处理有问题, dp[i][j]=min(1+max(dp[k-1][j-1],dp[i-k][j]))   k=1 to 楼数 dp[i][j]:i层楼扔,手里有j个ball 的次数 边界两个:1.dp[1][i]=1,第一层无论手里有几个鸡蛋都是1次,2.dp[i][1]=i

POJ 4968 DP||记忆化搜索

给出N个人的平局分X 根据GPA规则计算可能的最高平均GPA和最低平均GPA 可以DP预处理出来所有结果  或者记忆化搜索 DP: #include "stdio.h" #include "string.h" int inf=100000000; double a[11][1100],b[11][1100]; double Max(double a,double b) { if (a<b) return b; else return a; } double M

POJ 2029 DP || 暴力

在大矩形中找一个小矩形 使小矩形包含的*最多 暴力或者DP  水题 暴力: #include "stdio.h" #include "string.h" int main() { int n,m,w,i,s,t,j,k,l,ans,sum,x,y; int map[101][101]; while (scanf("%d",&w)!=EOF) { if(w==0) break; scanf("%d%d",&n,&

POJ 1160 DP

用数轴描述一条高速公路,有V个村庄,每一个村庄坐落在数轴的某个点上,需要选择P个村庄在其中建立邮局,要求每个村庄到最近邮局的距离和最小. cost记录每两个村庄之间建一个邮局的最小代价. 转移方程: dp[j][i]=Min(dp[j][i],dp[k][i-1]+cost[k+1][j]) 前j个村庄建i个邮局=前k个村庄建I-1个邮局+第k+1村庄到第j村庄建一个邮局的代价 #include "stdio.h" #include "string.h" int i