hdu5550 Game Rooms (动态规划)

来源:互联网 发布:c语言设计培训班 编辑:程序博客网 时间:2024/05/17 03:47

表示制杖,参考了一下别人的题解,做完发现自己整个人都不好了,竟然没有发现这么弱的dp方程,(我不知怎么的,一开始居然想了一个n^3的dp方程)

设dp[i][s]表示计算到第i个且将其放在该段的最后一个,这一段全为s(0和1分别表示两种运动)

那么dp方程就是dp[i][s] = min{dp[j][s^1] + valueSum(j+1, i)},  j < i

valueSum(i, j)表示[i, j]区间内的员工到最近运动室的距离和

#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int MAXN = 4005;const int INF = 0x3f3f3f3f;int n;long long a[2][MAXN], sum[2][MAXN], value[2][MAXN], dp[MAXN][2];long long leftCal(int l, int r, int s){long long x = value[s][r] - value[s][l-1];long long y = sum[s][r] - sum[s][l-1];return abs(x - y * (l - 1));}long long rightCal(int l, int r, int s){long long x = value[s][r] - value[s][l-1];long long y = sum[s][r] - sum[s][l-1];return abs(x - y * (r + 1));}long long areaDist(int l, int r, int s){if (l == 1) return rightCal(l, r, s);else if (r == n) return leftCal(l, r, s);else{int mid = (l + r) >> 1;return leftCal(l, mid, s) + rightCal(mid + 1, r, s);}}int main(){int T; scanf("%d", &T);for (int kk = 1; kk <= T; kk++){//inputscanf("%d", &n);sum[0][0] = sum[1][0] = 0LL;value[0][0] = value[1][0] = 0LL;for (int i = 1; i <= n; i++){scanf("%lld%lld", &a[0][i], &a[1][i]);sum[0][i] = sum[0][i-1] + a[0][i];sum[1][i] = sum[1][i-1] + a[1][i];value[0][i] = value[0][i-1] + a[0][i] * i;value[1][i] = value[1][i-1] + a[1][i] * i;}//initializememset(dp, INF, sizeof(dp));for (int i = 1; i < n; i++){for (int s = 0; s <= 1; s++)dp[i][s] = areaDist(1, i, s);}//dpfor (int i = 1; i <= n; i++){for (int s = 0; s <= 1; s++){for (int j = 1; j < i; j++)dp[i][s] = min(dp[i][s], dp[j][s^1] + areaDist(j + 1, i, s));}}//outputprintf("Case #%d: %lld\n", kk, min(dp[n][0], dp[n][1]));}return 0;}


0 0
原创粉丝点击