[ZOJ 3469] 푸드 딜리버리[기억화 검색]

2273 단어 dp
제목 링크: [ZOJ 3469] Food Delivery[기억화 검색]
주제 분석:
배달원은 X곳의 식당에서 출발해 고객에게 음식을 배달해야 하며, 배달원은 고객 입구를 지나가면 음식 제출 여부를 선택할 수 있다(모든 음식은 이미 배달형 손에 맡겨져 있다).모든 고객은 대기 시간이 상승함에 따라 괴기가 발생한다. 괴기치는bi이다. 현재 배달원은 V의 - 1회 방미터의 분당 속도로 음식을 배달한다(즉 미터당 V분). 가장 적게 발생하는 괴기치는 얼마냐고 물었다.
문제 해결 방법:
상태 dp[i][j][sta]를 설정하여 배달원에게 구간 [i,j]을 배달하고 최소한의 괴로움을 준다. sta가 0이면 배달원이 구간 왼쪽에 있고 1은 오른쪽에 있다.
그러면 dp[i][j][0]는 dp[i+1][j]에서만 올 수 있고, dp[i][j][1]는 dp[i][j-1]에서만 올 수 있다.이걸로 옮기면 돼.
개인적인 느낌:
비록 시합할 때 해내지 못했지만, 악기를 어떻게 처리하는지에 끼었다.그러나 이런 구간 DP는 이제 그렇게 징그럽지 않다.
구체적인 코드는 다음과 같습니다.
#include<algorithm>
#include<cctype>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iomanip>
#include<iostream>
#include<map>
#include<queue>
#include<set>
#include<sstream>
#include<stack>
#include<string>
#define ll long long
#define pr(x) cout << #x << " = " << (x) << '
'; using namespace std; const int MAXN = 1e3 + 11; ll dp[MAXN][MAXN][2]; struct P { ll x, b; bool operator < (const P &t)const { return x < t.x; } }a[MAXN]; int n; ll X, v, sum[MAXN]; ll dfs(ll l, ll r, int sta) { ll &ret = dp[l][r][sta]; if (ret >= 0) return ret; if (l == r) return ret = abs((X - a[l].x)) * v * sum[n]; if (sta == 0) { ll mul = sum[l] + sum[n] - sum[r]; ret = min(dfs(l + 1, r, 0) + (a[l + 1].x - a[l].x) * v * mul, dfs(l + 1, r, 1) + (a[r].x - a[l].x) * v * mul); } else { ll mul = sum[l - 1] + sum[n] - sum[r - 1]; ret = min(dfs(l, r - 1, 1) + (a[r].x - a[r - 1].x) * v * mul, dfs(l, r - 1, 0) + (a[r].x - a[l].x) * v * mul); } return ret; } int main() { while (~scanf("%d%d%lld", &n, &v, &X)) { for (int i = 1; i <= n; ++i) { scanf("%lld%lld", &a[i].x, &a[i].b); } sort(a + 1, a + n + 1); sum[0] = 0; for (int i = 1; i <= n; ++i) sum[i] = sum[i - 1] + a[i].b; memset(dp, -1, sizeof dp); printf("%lld
", min(dfs(1, n, 0), dfs(1, n, 1))); } return 0; }

좋은 웹페이지 즐겨찾기