Give you a Graph,you have to start at the city with ID zero.
Input
The first line is n(1<=n<=21) m(0<=m<=3)
The next n line show you the graph, each line has n integers.
The jth integers means the length to city j.if the number is -1 means there is no way. If i==j the number must be -1.You can assume that the length will not larger than 10000
Next m lines,each line has two integers a,b (0<=a,b<n) means the path must visit city a first.
The input end with EOF.
Output
For each test case,output the shorest length of the hamilton path.
If you could not find a path, output -1
Sample Input
3 0 -1 2 4 -1 -1 2 1 3 -1 4 3 -1 2 -1 1 2 -1 2 1 4 3 -1 1 3 2 3 -1 1 3 0 1 2 3
Sample Output
4 5
Hint
I think that all of you know that a!=b and b!=0 =。=
题意:求从0点开始的最短哈密顿路径,要求某些点必须在某些点之前经过(每个点只走一次,走完所有点)
思路:状压dp,dp[sta][end]表示已经走过的点的集合状态是sta,走过的最后一个点是end 的最短距离
#include<bits/stdc++.h>
//#include<cstdio>
//#include<algorithm>
//#include<cstring>
//#include<map>
//#include<iostream>
#pragma GCC optimize(3)
#define max(a,b) a>b?a:b
using namespace std;
typedef long long ll;
const int INF=0x3f3f3f3f;
int dp[1<<21][22];//dp[sta][end] 当前走过点的状态是sta,最后一个走过的点是end
int mp[25][25];
vector<int> pre[25];
int main(){
ios::sync_with_stdio(false);
cout.tie(NULL);
int n,m;
while(~scanf("%d%d",&n,&m)){
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
scanf("%d",&mp[i][j]);
if(mp[i][j]==-1) mp[i][j]=INF;
}
}
int up=(1<<n)-1;
for(int i=0;i<n;i++) vector<int>().swap(pre[i]);
for(int i=0;i<=up;i++) {
for(int j=0;j<n;j++){
dp[i][j]=INF;
}
}
for(int i=1;i<=m;i++){
int a,b;
scanf("%d%d",&a,&b);
pre[b].push_back(a);
}
dp[1][0]=0;
for(int i=0;i<=up;i++){//枚举状态(走过哪些点)
for(int j=0;j<n;j++){//枚举最后一个走过的点
if(dp[i][j]==INF) continue;//该状态还没走过
if((i&(1<<j))==0) continue;//j没走过 (用不到,不加也能过,上一个判断已经包含了)
for(int k=0;k<n;k++){//枚举下一个要走的点
if(i&(1<<k)) continue;//k点已经走过了
bool flag=true;
for(int v=0;v<pre[k].size();v++){//判断限定条件
int &p=pre[k][v];
if((i&(1<<p))==0) {//前节点没走过
flag=false;
break;
}
}
if(flag) dp[i|(1<<k)][k]=min(dp[i|(1<<k)][k],dp[i][j]+mp[j][k]);
}
}
}
int ans=INF;
for(int i=0;i<n;i++) {
ans=min(ans,dp[up][i]);
}
if(ans==INF) printf("-1\n");
else printf("%d\n",ans);
}
return 0;
}