codeforces-1130B. Two Cakes-题解--(有点难)
题目:
B.两个蛋糕
Sasha和Dima想买两个n层蛋糕。每个蛋糕应该由n个不同的层组成。层应该按照从最小到最大的顺序排列(从上到下)。
他们住在同一条街上,有2⋅n房屋在一行从左到右。每个房子都有一个糕点店,你可以在那里买一个蛋糕层。不幸的是,在每家糕点店只能买到一层,而且只能买到一种特定尺寸的:在第ii家,可以买到一层尺寸为ai(1≤ai≤n)的糕点。
由于这些人携带已经购买的层,这是不可能插入一个新的层在蛋糕中间,他们同意购买层从最小的到最大的。也就是说,他们每个人都按顺序购买层:1层、2层、3层,一直到n。
最初,Sasha和Dima位于第一个(最左边)房子附近。输出购买两个蛋糕总共需要走的最小距离。相邻两幢房子之间的距离正好是1。
输入
输入的第一行包含一个整数n——每个蛋糕的层数(1≤n≤10^5)。
第二行包含2⋅n个整数a1, a2,…,an, (1≤ai≤n),在ai等于层的大小,在i-th可以买房子。记住,每栋房子只能买一层。保证从1到n的每一个数字在a中都精确地出现两次。
输出
打印一个数字——买两个蛋糕的人总共要走的最小距离。男人可以在同一时间靠近同一所房子。他们从第一个(最左边的)房子附近开始。每个人都应该按照他们的大小购买n层。
例子
input
3.
1 1 2 2 3 3
output
9
input
2
2 1 1 2
output
5
input
4
4 1 3 2 2 3 1 4
output
17
思路
题目翻译:两个人要做N层蛋糕,已知一条街上的商店每家只能提供一个x层蛋糕,输出两个人组装成n层蛋糕总共需要步行的最少步数。
题目思路:用vector记录每一层蛋糕的店家地址,形成一个二维数组。对于第一层和第二层蛋糕,就有两种组合方式,用点dp的思路往后推。另外要注意数组的初始化,要插入两个0
My code
#include<iostream>
#include<cmath>
#include<vector>
using namespace std;
long long n,d[100005];
vector<long long> a[100005];//二维数组
int main()
{
//0 0 //输入4
//1 6 //4 1 3 2 2 3 1 4
//3 4
//2 5
//0 7
long long i,b,d1,d2;
cin >>n;
for(i = 0;i<2*n;i++){
cin >> b;
a[b].push_back(i);//将i放在第b行的尾部
}//二维数组里存的数字是表示步数
a[0].push_back(0);
a[0].push_back(0);
for(i = 1;i<=n;i++){
d1 = abs(a[i][0] - a[i-1][0]) + abs(a[i][1] - a[i-1][1]);
d2 = abs(a[i][0] - a[i-1][1]) + abs(a[i][1] - a[i-1][0]);
d[i] = d[i-1] + min(d1,d2);
}
cout<<d[n]<<endl;
return 0;
}
/**
* ┏┓ ┏┓+ +
* ┏┛┻━━━┛┻┓ + +
* ┃ ┃
* ┃ ━ ┃ ++ + + +
* ████━████+
* ◥██◤ ◥██◤ +
* ┃ ┻ ┃
* ┃ ┃ + +
* ┗━┓ ┏━┛
* ┃ ┃ + + + +Code is far away from
* ┃ ┃ + bug with the animal protecting
* ┃ ┗━━━┓ OC保佑,代码无bug
* ┃ ┣┓
* ┃ ┏┛
* ┗┓┓┏━┳┓┏┛ + + + +
* ┃┫┫ ┃┫┫
* ┗┻┛ ┗┻┛+ + + +
*/