IPUOJ24101旅行商问题(状压dp)
旅行商问题·基础版
题目↓(建议全屏看图)
挺简单的 集合状压,具体看代码吧
#include<bits/stdc++.h> using namespace std; #define fr(g,h) for(int g = 0; g < h; g++) const int N = 25, M = 2100000; int n,nn,mm,a[N][N],f[N][M]; inline void init () { scanf("%d",&n); fr(i,n) fr(j,n) cin >> a[i][j]; memset(f, 0x3f, sizeof f); } void floyd() { fr(k,n) fr(i,n) fr(j,n) a[i][j] = min(a[i][j], a[i][k] + a[k][j]); } void dp() { for(int s = 1; s <= (1 << n) - 1; s++) //从第一个开始走过 (这个地方s的优化还是蛮重要的,暴力开210万只能险过) fr(i,n) fr(j,n) if(s & (1 << j)) f[i][s|(1<<i)] = min(f[i][s|(1<<i)], f[j][s] + a[i][j]); } int main() { init(); f[0][1] = 0; floyd(); dp(); cout << f[0][(1<<n) - 1]; return 0; }
旅行商问题·进阶版
//旅行商2 #include <bits/stdc++.h> using namespace std; #define fr(g,h) for(int g = 0; g < h; g++) const int N = 13, M = 531441 * 3; //M是3的13次方 int pow3[N + 1], n; int a[N][N], f[N][M]; inline void init () { scanf("%d",&n); fr(i,n) fr(j,n) cin >> a[i][j]; memset(f, 0x3f, sizeof f); } void floyd() { fr(k,n) fr(i,n) fr(j,n) a[i][j] = min(a[i][j], a[i][k] + a[k][j]); } int main() { pow3[0] = 1; for (int i = 1; i <= N; ++i) pow3[i] = pow3[i - 1] * 3; //预处理3的指数表 init(); floyd(); int nn = pow3[n] - 1; f[0][1] = 0; for (int k = 1; k <= nn; k++) for (int i = 0; i < n; i++) { if (f[i][k] == 0x3f3f3f3f) continue; for (int j = 0; j < n; j++) { if (i == j) continue; int x = pow3[j]; if ((k / x) % 3 < 2) { int kn = k + x; f[j][kn] = min(f[j][kn], f[i][k] + a[i][j]); } } } printf("%d", f[0][nn]); return 0; }
满堂花醉三千客,一剑霜寒十四州