题目链接:http://poj.org/problem?id=3034
此题的状态方程很容易想出来,以时间为阶段划分,然后地图为状态,f[k][i][j]=Max{ f[k-1][x][y]+t | t=sum( map[k][p][q] && (p,q)在线段(i,j)-(x,y)上 }。
转移的时候用点小技巧就可以了,就是先把通方向上的单位整数向量求出来,在更新的时候逐个用 n*单位整数向量 (n满足距离不超过d) 来更新f[k][i][j],最后遍历一遍最值。
此题有一个很坑的trick:hammer可以在正整数坐标轴的外面,很坑啊有不有!!!足足贡献了4个WA= =
1 //STATUS:C++_AC_157MS_216KB 2 #include<stdio.h> 3 #include<stdlib.h> 4 #include<string.h> 5 #include<math.h> 6 #include<iostream> 7 #include<string> 8 #include<algorithm> 9 #include<vector> 10 #include<queue> 11 #include<stack> 12 using namespace std; 13 #define LL __int64 14 #define pii pair<int,int> 15 #define Max(a,b) ((a)>(b)?(a):(b)) 16 #define Min(a,b) ((a)<(b)?(a):(b)) 17 #define mem(a,b) memset(a,b,sizeof(a)) 18 #define lson l,mid,rt<<1 19 #define rson mid+1,r,rt<<1|1 20 const int N=32,INF=0x3f3f3f3f,MOD=100000000; 21 const double DNF=100000000000; 22 23 int dx[4]={1,1,-1,-1},dy[4]={1,-1,-1,1}; 24 int f[2][N][N],ma[11][N][N],lxy[N][2],cou; 25 int n,d,m; 26 27 int gcd(int a,int b){return b?gcd(b,a%b):a;} 28 29 int dist(int x1,int y1,int x2,int y2) 30 { 31 return (x1-x2)*(x1-x2)+(y1-y2)*(y1-y2); 32 } 33 34 int main() 35 { 36 // freopen("in.txt","r",stdin); 37 int i,j,k,ans,t,x,y,p,end,dir,nx,ny,q; 38 while(~scanf("%d%d%d",&n,&d,&m) && (n||d||m)) 39 { 40 end=-INF; 41 mem(ma,0); 42 mem(f,0); 43 while(m--){ 44 scanf("%d%d%d",&x,&y,&t); 45 if(t>end)end=t; 46 ma[t][x+d][y+d]=1; 47 } 48 for(cou=x=0;x<=d;x++) 49 for(y=0;y<=d;y++){ 50 if(dist(x,y,0,0)>d*d)continue; 51 t=gcd(x,y); 52 if(t<=1 && x+y){ 53 lxy[cou][0]=x; 54 lxy[cou++][1]=y; 55 } 56 } 57 n+=2*d; 58 d*=d; 59 for(k=p=1;k<=end;k++,p=!p){ 60 for(i=0;i<n;i++){ 61 for(j=0;j<n;j++){ 62 f[p][i][j]=Max(f[p][i][j],f[!p][i][j]+ma[k][i][j]); 63 for(dir=0;dir<4;dir++){ 64 for(q=0;q<cou;q++){ 65 x=lxy[q][0]*dx[dir]; 66 y=lxy[q][1]*dy[dir]; 67 nx=i+x,ny=j+y; 68 for(t=ma[k][i][j];dist(nx,ny,i,j)<=d 69 && nx>=0&&nx<n && ny>=0&&ny<n;nx+=x,ny+=y){ 70 t+=ma[k][nx][ny]; 71 f[p][nx][ny]=Max(f[p][nx][ny],f[!p][i][j]+t); 72 } 73 } 74 } 75 } 76 } 77 } 78 for(ans=-INF,i=0,p=!p;i<n;i++) 79 for(j=0;j<n;j++) 80 if(f[p][i][j]>ans)ans=f[p][i][j]; 81 82 printf("%d\n",ans); 83 } 84 return 0; 85 }