无聊的开车 (状压DP)

题目地址
每个起点与终点组成一个状态节点,然后实现状态转移,注意权值的计算,

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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值