PS:如果读过题了可以跳过题目描述直接到题解部分
提交链接:洛谷 T279725 搬砖
题目
题目背景
因为题目简单,所以 N S H NSH NSH不好好学习,最后到了工地搬砖。
题目描述
N
S
H
NSH
NSH 来到工地,俯视来看,工地是一个二维平面,现在四周散落了
n
n
n 块砖。第
i
i
i个砖在坐标
(
x
i
,
y
i
)
(x_i, y_i)
(xi,yi) 上。
N
S
H
NSH
NSH 现在需要把
n
n
n 块砖全部搬运到目的地处。
N
S
H
NSH
NSH 决定开始搬砖,但是他同时最多只能携带两块砖,而且一旦他拿起一块砖,就必须要把砖放到目的地处,不允许放在中途的某个地方。
搬砖的时候,对于每一次行动,从
(
x
a
,
y
a
)
(x_a,y_a)
(xa,ya) 按照直线走到
(
x
b
,
y
b
)
(x_b,y_b)
(xb,yb) 要花费
(
x
a
−
x
b
)
2
+
(
y
a
−
y
b
)
2
(x_a-x_b)^2+(y_a-y_b)^2
(xa−xb)2+(ya−yb)2 的时间。 拿起砖和放下砖不消耗时间。
注意,每次行动
N
S
H
NSH
NSH 只能走一条直线,且每次行动的终止点只能是当前某块砖的所在地或者目的地。
初始时刻,
N
S
H
NSH
NSH 在
(
x
0
,
y
0
)
(x_0,y_0)
(x0,y0) 处。
希望你找到一个搬砖顺序,使得
N
S
H
NSH
NSH 把所有砖搬到目的地花费的时间最少。
输入格式
第一行,两个整数
x
0
,
y
0
x_0,y_0
x0,y0。
接下来一行,一个整数
n
n
n,表示砖的数量。
接下来
n
n
n 行,每行两个整数
x
i
,
y
i
x_i,y_i
xi,yi。
输出格式
第一行,一个整数,表示把所有砖搬到目的地花费的最少时间。
第二行,
n
n
n 个整数,表示最优方案下,拾起每块砖的前后顺序。如果有多个答案,输出字典序最小的
解。
样例1
输入
0 0
2
1 1
-1 1
输出
8
1 2
样例2
输入
1 1
3
4 3
3 4
0 0
输出
32
1 2 3
样例3
输入
122 116 20
12 34
166 166
56 131
114 76
22 115
15 85
5 9
92 195
154 135
64 200
105 19
122 127
187 157
112 159
162 34
140 155
113 56
148 54
55 140
129 86
输出
145168
1 7 2 13 3 19 4 20 5 6 8 10 9 16 11 17 12 14 15 18
提示
对 100% 的数据满足:
n
≤
20
,
∣
x
i
∣
,
∣
y
i
∣
≤
100
n\le 20, |x_i|,|y_i|\le 100
n≤20,∣xi∣,∣yi∣≤100
保证给出的坐标互不相同。
数据
Subtask 1
1 ≤ n ≤ 5 1\le n\le 5 1≤n≤5
Subtask 2
5 ≤ n ≤ 10 5\le n\le 10 5≤n≤10
Subtask 3
10 ≤ n ≤ 20 10\le n\le 20 10≤n≤20
题解
暴力深搜
深搜的同时进行剪枝,并保存当前方案即可。
代码实现
//洛谷 T279725 搬砖
#pragma GCC optimize(3)
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int x,y;
int n;
int ans;
int c[25];
int b[25][25];
int num[25];
int v[25];
int f[(1<<22)+10];
struct z{
int x,y;
}a[25];
void in(int &x){
int nt;
int neg=1;
x=0;
while(!isdigit(nt=getchar())){
if(nt=='-'){
neg=-1;
}
}
x=nt^'0';
while(isdigit(nt=getchar())){
x=(x<<3)+(x<<1)+(nt^'0');
}
x*=neg;
}
int len(int x,int y){
return x*x+y*y;
}
void dfs(int p,int res,int len,int s){
if(res>f[s]){
return;
}
if(res>=ans){
return;
}
if(v[p]){
dfs(p+1,res,len,s);
return;
}
if(p>n){
ans=res;
for(int i=1;i<=n;++i){
num[i]=c[i];
}
return;
}
c[len+1]=p;
dfs(p+1,res+b[0][p]*2,len+1,s+(1<<p));
for(int i=p+1;i<=n;++i){
if(!v[i]){
v[i]=1;
c[len+2]=i;
dfs(p+1,res+b[0][p]+b[p][i]+b[i][0],len+2,s+(1<<p)+(1<<i));
v[i]=0;
}
}
f[s]=res;
return;
}
int main(){
register int i,j;
in(a[0].x);
in(a[0].y);
in(n);
for(i=1;i<=n;++i){
in(a[i].x);
in(a[i].y);
}
for(i=1;i<=n;++i){
for(j=0;j<i;++j){
b[i][j]=b[j][i]=len(a[i].x-a[j].x,a[i].y-a[j].y);
}
}
ans=0x3f3f3f3f;
memset(f,0x3f3f3f3f,sizeof(f));
dfs(1,0,0,0);
printf("%d\n",ans);
for(i=1;i<n;++i){
printf("%d ",num[i]);
}
printf("%d\n",num[n]);
return 0;
}