3122 奶牛代理商 VIII
时间限制: 3 s
空间限制: 256000 KB
题目等级 : 大师 Master
对于每一个城市只有去过和没去过两种状态,用一个二进制数s来表示
f[s][i]当前在第i个城市,状态为s时的最小花费,&运算有0落0,所以s&1<<(j-1)保证了
i城市的s状态 |运算有1落1 这样便可以找到一个从j到i的状态,用于更新答案
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 int mp[20][20]; 6 int f[70010][20]; 7 int n,ans = 1e9; 8 void floyd() 9 { 10 for (int k=1; k<=n; ++k) 11 for (int i=1; i<=n; ++i) 12 for (int j=1; j<=n; ++j) 13 if (i!=j&&k!=i) 14 mp[i][j] = min(mp[i][j],mp[i][k]+mp[k][j]); 15 } 16 void dp() 17 { 18 memset(f,0x3f,sizeof(f)); 19 f[1][1] = 0; 20 for (int s=0; s<=(1<<n)-1; s++) 21 for (int i=1; i<=n; i++) 22 { 23 for (int j=1; j<=n; j++) 24 if (s&1<<(j-1)&&i!=j) 25 f[s|(1<<i-1)][i] = min(f[s|(1<<i-1)][i],f[s][j]+mp[j][i]); 26 } 27 for(int i=2; i<=n; i++) 28 ans = min(ans,f[(1<<n)-1][i]+mp[i][1]); 29 } 30 int main() 31 { 32 scanf("%d",&n); 33 for (int i=1; i<=n; ++i) 34 for (int j=1; j<=n; ++j) 35 scanf("%d",&mp[i][j]); 36 floyd(); 37 dp(); 38 printf("%d",ans); 39 return 0; 40 }