很经典的动态规划。 关键是给定起始点和终止点,如何快速找到直线经过的整数坐标点。参考别人的博客,写了一段个人认为很赞的代码。 #include "string.h" #include "math.h" #include <queue> #include <algorithm> #include <iostream> #define MinN(x,y) ((x)<(y)?(x):(y)) #define MaxN(x,y) ((x)>(y)?(x):(y)) #define _clr(a,b) memset(a,b,sizeof(a)) template<class T> void _swap(T& a,T& b) {T temp;temp=a;a=b;b=temp;} template<class T> T _abs(T a) {if(a<0) return -a;else return a;} using namespace std; int n,d,m; struct node { int x,y,t; }mole[1005]; int CMP(const void* a,const void * b) { node *c=(node*)a,*d=(node*)b; return c->t-d->t; } bool exist[35][35]; int dist(int x,int y,int x2,int y2) { return (x-x2)*(x-x2)+(y-y2)*(y-y2); } int score[32][32][13]; int Gcd(int x,int y) { int t; while(y!=0) { t=x; x=y; y=t%y; } return x; } int cal(int x1,int y1,int x2,int y2)//这个函数,个人很喜欢 { int pass=0,ax=x2-x1,ay=y2-y1; if(ax==0&&ay==0) return exist[x1][y1]?1:0; else if(ax==0||ay==0) { if(ax==0) ay=ay/_abs(ay); if(ay==0) ax=ax/_abs(ax); } else { int m=Gcd(_abs(ax),_abs(ay)); ax=ax/m; ay=ay/m; } while(x1!=x2||y1!=y2) { if(exist[x1][y1]) pass++; x1+=ax; y1+=ay; } if(exist[x2][y2]) pass++; return pass; } int main() { while(1) { scanf("%d%d%d",&n,&d,&m); if(n==0&&d==0&&m==0) break; for(int i=0;i<m;i++) { scanf("%d%d%d",&mole[i].x,&mole[i].y,&mole[i].t); } qsort(mole,m,sizeof(mole[0]),CMP); _clr(score,0); mole[m].t=-1; int j=0; for(int i=1;i<=mole[m-1].t;i++) { _clr(exist,0); for(;mole[j].t==i;j++) { exist[mole[j].x+d] [mole[j].y+d]=true; } int top=n+2*d; for(int x1=0;x1<top;x1++) { for(int y1=0;y1<top;y1++) { for(int x2=0;x2<top;x2++) { for(int y2=0;y2<top;y2++) { if(dist(x1,y1,x2,y2)>d*d) continue; int pass=cal(x1,y1,x2,y2); score[x1][y1][i]=MaxN(score[x1][y1][i],score[x2][y2][i-1]+pass); } } } } } int ans=0; for(int k=0;k<(n+d);k++) { for(int l=0;l<(n+d);l++) { ans=MaxN(score[k][l][mole[m-1].t],ans); } } printf("%d/n",ans); } return 0; }