第一次走用dfs枚举每种情况,第二次走用dp求剩下的最大值
设一个点集q用来保存有价值的点,排序,在最后加一个终点:x=m+1,y=m+1,v=0 //m是矩阵长宽
因为v=0的点是没有意义的,所以忽略它们,用q进行dfs
设当前点在q中的下标为p,已经积累的分数为score:
for(int i=p+1;i<=n+1;i++){ if(q[i].y>=q[p].y){//可以到达 a[q[i].x][q[i].y]=0; dfs(i,score+q[i].v); a[q[i].x][q[i].y]=q[i].v; } }
当p=n+1时,到了终点(n是有价值点的个数,n+1为最后添加的终点)
在残缺的a中dp找到第二次的最大价值,更新ans即可
代码如下:
#include<iostream> #include<algorithm> using namespace std; struct Point{ int x,y; int v; }q[105]; bool cnt(Point c,Point d){ return c.x<d.x || (c.x==d.x && c.y<d.y); } int n,m;//m是边长,n是有值的点的个数 int a[15][15]; int d[15][15]; int ans=0; int dp(){ for(int i=1;i<=m;i++){ for(int j=1;j<=m;j++){ d[i][j]=max(d[i-1][j],d[i][j-1])+a[i][j]; } } return d[m][m]; } void dfs(int p,int score){ if(p==n+1){ int c=dp(); if(ans<c+score)ans=c+score; return; } for(int i=p+1;i<=n+1;i++){ if(q[i].y>=q[p].y){//可以到达 a[q[i].x][q[i].y]=0; dfs(i,score+q[i].v); a[q[i].x][q[i].y]=q[i].v; } } } int main(){ cin>>m; for(n=1;true;n++){ cin>>q[n].x>>q[n].y>>q[n].v; if(q[n].x==0){n--;break;} a[q[n].x][q[n].y]=q[n].v; } sort(q+1,q+n+1,cnt); q[n+1].x=m+1;q[n+1].y=m+1;q[n+1].v=0;//终点 dfs(0,0); cout<<ans<<endl; return 0; }
如果你看着那个a和q有点重复不爽,可以试着直接在q上dp,这样就可以省去a了
ps:code上用operator为什么编译不过去!!求解!!