Travelling
Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 5765 Accepted Submission(s): 1858
題意:要走完所有的城市,每條邊有一個代價,求走完所有的城市的最小代價,起初沒看到每個城市最多可走兩邊。
思路:用二進制的狀態壓縮果然wa了,用三進制的狀態壓縮,先把進製表打好,然後用一個二維的數組表示出這個數每位在三進制下的狀態,狀態轉移。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<map>
#include<cstring>
#include<map>
#include<set>
#include<queue>
#include<stack>
using namespace std;
const double eps = 1e-10;
const int inf = 0x3f3f3f3f, N = 6e4;
typedef long long ll;
int dp[N][12], Map[12][12], n, m, three[12], vis[N][12];
void init()
{
three[0] = 1;
for(int i = 1; i<=10; i++)
three[i] = three[i-1] * 3;
for(int i = 0; i<three[10]; i++)
{
int temp = i;
for(int j = 1; j<=10; j++)
{
vis[i][j] = temp % 3;
temp /= 3;
}
}
}
int main()
{
init();
while(~scanf("%d%d", &n, &m))
{
memset(Map, 0x3f, sizeof(Map));
int u, v, w;
while(m--)
{
scanf("%d%d%d", &u, &v, &w);
Map[u][v] = Map[v][u] = min(w, Map[u][v]);
}
memset(dp, 0x3f, sizeof(dp));
int num = three[n] - 1;
for(int i = 1; i<=n; i++)
dp[three[i-1]][i] = 0;
int ans = inf;
for(int i = 1; i<=num; i++)
{
for(int j = 1; j<=n; j++)
{
if(dp[i][j] == inf)
continue;
for(int k = 1; k<=n; k++)
{
if(vis[i][k]>=2 || Map[j][k] == inf || j == k)
continue;
dp[i + three[k-1]][k] = min(dp[i + three[k-1]][k], dp[i][j] + Map[j][k]);
}
}
}
for(int i = 1; i<=num; i++)
{
int ok = 1;
for(int j = 1; j<=n; j++)
if(!vis[i][j])
{
ok = 0;
break;
}
if(ok)
for(int j = 1; j<=n; j++)
ans = min(dp[i][j], ans);
}
if(ans != inf)
cout<<ans<<endl;
else cout<<-1<<endl;
}
return 0;
}