ZOJ 3469 Food Delivery(DP)

来源:互联网 发布:淘宝网网上购物 编辑:程序博客网 时间:2024/06/05 07:34

思路:把小于x和大于x存成两个集合,然后dp[i][j][v]表示左边送完i个,右边送完j个,现在位置在左/右的代价,然后进行转移即可,具体转移见代码

代码:

#include <cstdio>#include <cstring>#include <algorithm>using namespace std;typedef long long ll;const int N = 1005;const ll INF = 0x3f3f3f3f3f3f3f;int n, v, x, ln, rn;ll dp[N][N][2];struct SB {int x, b;SB() {}SB(int x, int b) {this->x = x;this->b = b;}} l[N], r[N];int suml[N], sumr[N];bool cmp1(SB a, SB b) {return a.x < b.x;}bool cmp2(SB a, SB b) {return a.x > b.x;}int main() {while (~scanf("%d%d%d", &n, &v, &x)) {ln = rn = 0;int a, b;while (n--) {scanf("%d%d", &a, &b);if (a < x) l[++ln] = SB(a, b);if (a > x) r[++rn] = SB(a, b);}sort(l + 1, l + ln + 1, cmp2);sort(r + 1, r + rn + 1, cmp1);l[0].x = r[0].x = x;for (int i = 0; i <= ln; i++)for (int j = 0; j <= rn; j++)dp[i][j][0] = dp[i][j][1] = INF;dp[0][0][0] = dp[0][0][1] = 0;for (int i = 1; i <= ln; i++)suml[i] = suml[i - 1] + l[i].b;for (int i = 1; i <= rn; i++)sumr[i] = sumr[i - 1] + r[i].b;for (int i = 0; i <= ln; i++) {for (int j = 0; j <= rn; j++) {int tot = v * (suml[ln] - suml[i] + sumr[rn] - sumr[j]);if (i != ln) { dp[i + 1][j][0] = min(dp[i + 1][j][0], dp[i][j][0] + (l[i].x - l[i + 1].x) * tot);dp[i + 1][j][0] = min(dp[i + 1][j][0], dp[i][j][1] + (r[j].x - l[i + 1].x) * tot);}if (j != rn) {dp[i][j + 1][1] = min(dp[i][j + 1][1], dp[i][j][0] + (r[j + 1].x - l[i].x) * tot);dp[i][j + 1][1] = min(dp[i][j + 1][1], dp[i][j][1] + (r[j + 1].x - r[j].x) * tot);}}}printf("%lld\n", min(dp[ln][rn][0], dp[ln][rn][1]));}return 0;}


0 0
原创粉丝点击