加油站任务变化的DP算法
DP algorithm with variation of gas station task
我有一个问题,我从 A 点到 B 点,距离定义为 l
。在我的车里,我有一辆坦克,只能让我行驶 b
公里。在 n
个地方有加油站和加满油箱的费用(我只能加满)。我从满罐开始。
以最少的成本从高速公路起点到终点最有效的算法是什么?
我最近的想法:
使用 window 滑动最小值算法找到(长度为 b
)成本最小的站点。代码:
int n, range, targetDist;
scanf("%d %d %d", &n, &targetDist, &range);
int di, ci;
for (int k = 1; k <= n; k++)
{
scanf("%d %d", &di, &ci);
D[k] = di;
C[k] = ci;
}
D[0] = C[0] = bestcost[0] = 0;
for (int i = 1; i < n+1; ++i)
{
bestcost[i] = 1 << 30;
for (int j = 0; j < i; ++j)
{
int xx = bestcost[j] + C[i];
if (D[i] - D[j] <= range && xx < bestcost[i])
{
bestcost[i] = xx;
printf("(%d, %d)\n", i, bestcost[i]);
}
}
}
输入为:
3 8 4
2 1
4 2
6 3
输出为:
(1, 1)
(2, 2)
(3, 4)
所以它对应于到(i, cost(i))的成本-到达第i站,我必须支付cost(i)。
如何使用该信息找到整个距离的最低成本?
我找到了一种使用滑动 window 算法在 O(n) 时间内完成此操作的方法:
#include <vector>
#include <algorithm>
#include <deque>
#include <stdio.h>
typedef unsigned long long int ulli;
using namespace std;
void sliding_window_minimum(vector<pair<ulli, ulli>> st, ulli n, ulli targetDist, ulli range)
{
deque<pair<ulli, ulli>> minimize;
ulli j = 0;
for (ulli i = 0; i < n; i++)
{
if (st[i].first <= range)
{
while (!(minimize.empty()) && (minimize.back().second > st[i].second))
{
minimize.pop_back();
}
minimize.push_back(st[i]);
j++;
}
else
{
break;
}
}
for (ulli k = j; k < n; k++)
{
while (!(minimize.empty()) && ((st[k].first - minimize.front().first) > range))
{
minimize.pop_front();
}
if (minimize.empty()) {
break;
}
ulli tempCost = st[k].second + minimize.front().second;
while (!(minimize.empty()) && (minimize.back().second > tempCost))
{
minimize.pop_back();
}
minimize.push_back(make_pair(st[k].first, tempCost));
}
while (!(minimize.empty()) && ((targetDist - minimize.front().first) > range))
{
minimize.pop_front();
}
if (minimize.empty())
{
printf("NIE\n");
}
else
{
printf("%llu", minimize.front().second);
}
}
int main()
{
ulli n, d, b;
scanf("%llu %llu %llu", &n, &d, &b);
if (b >= d)
{
printf("%d", 0);
return 0;
}
int temp = n;
ulli d1, c1;
vector<pair<ulli, ulli>> st;
st.reserve(n+1);
while (temp--)
{
scanf("%llu %llu", &d1, &c1);
st.push_back(make_pair(d1, c1));
}
sliding_window_minimum(st, n, d, b);
}
我有一个问题,我从 A 点到 B 点,距离定义为 l
。在我的车里,我有一辆坦克,只能让我行驶 b
公里。在 n
个地方有加油站和加满油箱的费用(我只能加满)。我从满罐开始。
以最少的成本从高速公路起点到终点最有效的算法是什么?
我最近的想法:
使用 window 滑动最小值算法找到(长度为 b
)成本最小的站点。代码:
int n, range, targetDist;
scanf("%d %d %d", &n, &targetDist, &range);
int di, ci;
for (int k = 1; k <= n; k++)
{
scanf("%d %d", &di, &ci);
D[k] = di;
C[k] = ci;
}
D[0] = C[0] = bestcost[0] = 0;
for (int i = 1; i < n+1; ++i)
{
bestcost[i] = 1 << 30;
for (int j = 0; j < i; ++j)
{
int xx = bestcost[j] + C[i];
if (D[i] - D[j] <= range && xx < bestcost[i])
{
bestcost[i] = xx;
printf("(%d, %d)\n", i, bestcost[i]);
}
}
}
输入为:
3 8 4
2 1
4 2
6 3
输出为:
(1, 1)
(2, 2)
(3, 4)
所以它对应于到(i, cost(i))的成本-到达第i站,我必须支付cost(i)。
如何使用该信息找到整个距离的最低成本?
我找到了一种使用滑动 window 算法在 O(n) 时间内完成此操作的方法:
#include <vector>
#include <algorithm>
#include <deque>
#include <stdio.h>
typedef unsigned long long int ulli;
using namespace std;
void sliding_window_minimum(vector<pair<ulli, ulli>> st, ulli n, ulli targetDist, ulli range)
{
deque<pair<ulli, ulli>> minimize;
ulli j = 0;
for (ulli i = 0; i < n; i++)
{
if (st[i].first <= range)
{
while (!(minimize.empty()) && (minimize.back().second > st[i].second))
{
minimize.pop_back();
}
minimize.push_back(st[i]);
j++;
}
else
{
break;
}
}
for (ulli k = j; k < n; k++)
{
while (!(minimize.empty()) && ((st[k].first - minimize.front().first) > range))
{
minimize.pop_front();
}
if (minimize.empty()) {
break;
}
ulli tempCost = st[k].second + minimize.front().second;
while (!(minimize.empty()) && (minimize.back().second > tempCost))
{
minimize.pop_back();
}
minimize.push_back(make_pair(st[k].first, tempCost));
}
while (!(minimize.empty()) && ((targetDist - minimize.front().first) > range))
{
minimize.pop_front();
}
if (minimize.empty())
{
printf("NIE\n");
}
else
{
printf("%llu", minimize.front().second);
}
}
int main()
{
ulli n, d, b;
scanf("%llu %llu %llu", &n, &d, &b);
if (b >= d)
{
printf("%d", 0);
return 0;
}
int temp = n;
ulli d1, c1;
vector<pair<ulli, ulli>> st;
st.reserve(n+1);
while (temp--)
{
scanf("%llu %llu", &d1, &c1);
st.push_back(make_pair(d1, c1));
}
sliding_window_minimum(st, n, d, b);
}