题目地址
每个起点与终点组成一个状态节点,然后实现状态转移,注意权值的计算,
dis -> 等于上一个点的终点到下一个点的起点+ 下一个点的起点到下一个点的乘2.
和哈密顿的那个类似:
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#include<bits/stdc++.h>
#define int long long
using namespace std;
typedef pair<int,int> pii;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const double eps = 1e-5;
const int mod = 1000000007;
const int N = 1e5+10;
int dp[N][20];
struct Node{
int x1,y1,x2,y2;
}node[20];
int dis(int x,int y){
int a = node[x].x2,b = node[x].y2,c = node[y].x1,d = node[y].y1;
int e = node[y].x2,f = node[y].y2;
return (abs(a-c)+abs(b-d)+2*abs(c-e)+2*abs(d-f));
}
signed main(){
// IOS;
#ifdef ddgo
freopen("C:\\Users\\asus\\Desktop\\ddgoin.txt","r",stdin);
#endif
int n;
while(cin>>n){
for(int i=1;i<=n;i++){
int a,b,c,d; cin>>a>>b>>c>>d;
node[i] = {a,b,c,d};
}
memset(dp,INF,sizeof(dp));
dp[0][0] = 0;
for(int i=1;i<(1<<n);i++)
for(int j=0;j<n;j++)
if((i>>j)&1){//上一个状态时0
if((i-(1<<j)) == 0) dp[i][j+1] = dis(0,j+1);
else{//否则寻找上一个状态
for(int k=0;k<n;k++){
if(((i-(1<<j))>>k)&1){
dp[i][j+1] = min(dp[i][j+1],dp[(i-(1<<j))][k+1]+dis(k+1,j+1));
}
}
}
}
int mi = INF;
for(int i=1;i<=n;i++) mi = min(dp[(1<<n)-1][i],mi);
cout<<mi<<"\r\n";
}
return 0;
}