poj 3311Hie with the Pie
题意:一个送披萨的,每次送外卖不超过10个地方,给你这些地方之间的时间,求送完外卖回到店里的总时间最小。
解法一:
这个n不大,即使是NP问题也才1E6多一些所以可以dfs();具体的回溯方法结合dance link 就可以;
#include <cstdio> #include <algorithm> #include <cmath> #include <cstdlib> #include <cstring> using namespace std; int Map[11][11]; int Stack[11],pos; int left[11]; int right[11]; int n,ans,tmp,num;//比较怕爆栈 放到内存理好 void inint() { ans=0x7fffffff; pos=0; for(int i=0;i<=n;i++) left[i]=i-1,right[i]=i+1; for(int k=0;k<=n;k++)for(int i=0;i<=n;i++)for(int j=0;j<=n;j++) Map[i][j]=min(Map[i][j],Map[i][k]+Map[k][j]); } void make() { tmp=Map[0][Stack[0]]; for(int i=1;i<pos;i++) tmp+=Map[Stack[i-1]][Stack[i]]; tmp+=Map[Stack[pos-1]][0]; ans=min(ans,tmp); } void dfs() { //system("pause"); if(num==n){make();return;} for(int i=right[0];i<=n;i=right[i]) { num++; right[ left[i] ]=right[i]; left [ right[i]]=left[i]; Stack[pos++]=i; dfs(); num--; right[ left[i] ]=i; left [ right[i]]=i; pos--; } } int main() { while(~scanf("%d",&n)) { if(n==0) return 0; for(int i=0;i<=n;i++) for(int j=0;j<=n;j++) scanf("%d",&Map[i][j]); inint(); dfs(); printf("%d\n",ans); } return 0; }
解法2 :我交完了发现怎么都是 0MS 我的200多点;
仔细想了想可以用DP 解决NP 问题 dp[i][j] = min( dp[i][j ] , dp[i^(1<<j)][k] + dis[k][j] );(dp[i][j] 中 i 是二进制数 每一位表示这一味走没走过;
1 #include <cstdio> 2 #include <algorithm> 3 #include <cmath> 4 #include <cstdlib> 5 #include <cstring> 6 using namespace std; 7 const int INF=1<<30; 8 int dp[1<<11][11]; 9 int n; 10 int Map[15][15]; 11 void inint() 12 { 13 dp[0][0]=0; 14 for(int i=1;i<(1<<11);i++)for(int j=0;j<11;j++)dp[i][j]=INF; 15 16 for(int k=0;k<=n;k++)for(int i=0;i<=n;i++)for(int j=0;j<=n;j++) 17 Map[i][j]=min(Map[i][k]+Map[k][j],Map[i][j]); 18 } 19 void solve() 20 { 21 for(int i=1;i<(1<<n);i++) 22 for(int j=0;j<n;j++) 23 { 24 if(0==(i&(1<<j))) continue; 25 if(i==(1<<j)) dp[i][j]=Map[0][j+1]; 26 else 27 { 28 for(int k=0;k<n;k++) 29 if(k!=j&&(i&(1<<k))) 30 dp[i][j]=min(dp[i][j],dp[i^(1<<j)][k]+Map[k+1][j+1]); 31 } 32 } 33 int ans=INF; 34 for(int i=0;i<n;i++) 35 ans=min(ans,dp[(1<<n)-1][i]+Map[i+1][0]); 36 printf("%d\n",ans); 37 } 38 int main() 39 { 40 while(~scanf("%d",&n)) 41 { 42 if(n==0)return 0; 43 for(int i=0;i<=n;i++)for(int j=0;j<=n;j++) 44 scanf("%d",&Map[i][j]); 45 inint(); 46 solve(); 47 } 48 return 0; 49 }