题意 给了一个n*m的网格 然后一台挖掘机从(0,0) 这个位置出发,收集完全部的石头回到(0,0)挖掘机可以有无限的载重 用旅行商处理 dp[k][i] 表示在这个集合中最后到达i的最小距离,用集合上的dp, dp[S|(1<<j)][j]=min(dp[S|(1<<j)][j],d[S][i]+dist[i][j]);
#include <iostream> #include <cstdio> #include <string.h> #include <algorithm> #include <cmath> using namespace std; const int INF = 50*50*50; struct point{ int x,y; }P[10]; int dist[10][10]; int dp[1<<10][10]; int main() { int n,m; while(scanf("%d%d",&n,&m)==2){ int num=0; for(int i=0; i<n; ++i) for(int j=0; j<m; ++j){ int a; scanf("%d",&a); if(a>0){ P[num].x=i; P[num].y=j; ++num; } } if(num==0){ printf("0 "); continue; } for(int i=0; i<num; ++i) for(int j=0; j<num; ++j) dist[i][j]=dist[j][i]=abs(P[i].x-P[j].x)+abs(P[i].y-P[j].y); for(int s=0; s<1<<num; ++s) fill(dp[s],dp[s]+num,INF); dp[0][0]=0; for(int i=0; i<num; ++i) dp[1<<i][i]=abs(P[i].x)+abs(P[i].y); for(int S=1; S<1<<num; ++S){ for(int i=0; i<num; ++i) if( S&(1<<i) ){ for(int j=0; j<num; ++j) dp[S|(1<<j)][j]=min(dp[ S|(1<<j)][j],dp[S][i]+dist[i][j]); } } int ans=INF; for(int i=0; i<num; ++i) ans=min(ans,dp[(1<<num)-1][i]+abs(P[i].x)+abs(P[i].y)); printf("%d ",ans); } return 0; }
d