2019 뉴커머스 여름방학 멀티스쿨 캠프(10차전) J Wood Processing

27335 단어 DP
nnn빠른 널빤지, 합성 kkk 널빤지.같은 높이를 합칠 수 있고, 다른 높이를 합치면 높은 널빤지를 낮은 널빤지와 똑같이 잘라야 한다.합성kkk덩어리는 최소한 널빤지 면적을 얼마나 낭비하느냐고 물었다.문제풀이: dp[i][j]는 전j개 합성i개 널빤지의 최소 소비 면적을 나타낸다.전이 방정식은 dp [i] [j] = m in(dp [ii-1] [k] + s um [j]: [j] [j] [j] = m [k] = m in (dp [ii 1] [k] [j] [k] + h [k] (w [k]), d p [i] [j] dp[i] [j] = min(dp [i-1] [k] [k] + sum [j] [k] - s[k] [[k] + h[k] + h[k] + h[[[k+ 1] + (w[[[k] * (w[[j] - [k] [[k] [[k] [[k]] [j] [[j]] [j] [j]]]]]]]]]]]]k]+sum[j]--sum[k]+h[k+1]∗(w[j]--w[k]), dp[i][j]) 중 ww는 너비 접두사와 sum sum sum는 면적 접두사와전이의 공헌은,
가령 kk에서 lll보다 낫다고 가정하면,다음과 같이: dp [ii-4-1] [k] + s u m [j]: [k] - h[k + 1] (w [j] [k] + s u m [k] +sum[j]-sum[l]+h[l+1]*(w[j]-w[l])dp[i-1][k]+sum[j]--sum[k]--h[k+1]∗(w[j]--w[k])=dp[i-1][l]+sum[j]--sum[l]+h[l+1]?(w[j]]-w[wl]]]]]-[wwwl]]][wwl]) 병합 항목화 간략화,(d p [i 내지 1] [k] 시우 m [k] + h [k + 1] 및 w [k]) - (dp [i 1] [l] [l] [k] - [k] - [k + h [k + 1] - h [k + 1] - h [k + 1] - h [l + 1] <w [j] [j] [w[j] [dp[i-1] [i-1] [k] [k] + [k] + h [k] w [k] w [k] w [k] w [k] w [k] + 1] - [k] [k] [w[k] [k] [h[k] [k] [k] [k] [k+ + 1] [k] [k] [k] [k] [k] [w] [k] [h[{h[k+1]-h[l+1]}h[k+1]--h[l+1](dp[i-1][k]--sum[k]+h[k+1]\w[k])--(dp[i-1][l]--sum[l]+h[l+1]\w[l])#include "bits/stdc++.h" using namespace std; typedef long long LL; typedef unsigned long long uLL; typedef __int128 LLL; typedef pair<LLL, LLL> P; #define VNAME(value) (#value) #define bug printf("*********
");
#define debug(x) cout< #define mid ((l + r) >> 1) #define chl 2 * k + 1 #define chr 2 * k + 2 #define lson l, mid, chl #define rson mid + 1, r, chr #define eb(x) emplace_back(x) #define pb(x) emplace_back(x) #define mem(a, b) memset(a, b, sizeof(a)); const LL mod = (LL) 1e9 + 7; const int maxn = (int) 5e3 + 5; const LL INF = 0x7fffffff; const LL inf = 0x3f3f3f3f; const double eps = 1e-8; #ifndef ONLINE_JUDGE clock_t prostart = clock(); #endif void f() { #ifndef ONLINE_JUDGE freopen("../data.in", "r", stdin); #endif } template<typename T> void read(T &w) {// char c; while (!isdigit(c = getchar())); w = c & 15; while (isdigit(c = getchar())) w = w * 10 + (c & 15); } template<typename T> void output(T x) { if (x < 0) putchar('-'), x = -x; int ss[55], sp = 0; do ss[++sp] = x % 10; while (x /= 10); while (sp) putchar(48 + ss[sp--]); } LLL dp[maxn][maxn]; P dat[maxn]; LLL sum[maxn]; LLL w[maxn]; LLL getup(int i, int j, int k) { return (dp[i - 1][j] - sum[j] + w[j] * dat[j + 1].first) - (dp[i - 1][k] - sum[k] + w[k] * dat[k + 1].first); } LLL getdown(int j, int k) { return dat[j + 1].first - dat[k + 1].first; } LLL getdp(int i, int j, int k) { return dp[i - 1][k] + sum[j] - sum[k] - dat[k + 1].first * (w[j] - w[k]); } int p[maxn]; int main() { f(); int n, k; read(n); read(k); for (int i = 1; i <= n; i++) { read(dat[i].second); read(dat[i].first); } sort(dat + 1, dat + n + 1); for (int i = 1; i <= n; i++) { sum[i] = sum[i - 1] + dat[i].second * dat[i].first; w[i] = w[i - 1] + dat[i].second; } mem(dp, inf); dp[0][0] = 0; for (int i = 1; i <= k; i++) { int head = 0, tail = 1; for (int j = 1; j <= n; j++) { while (head + 1 < tail && getup(i, p[head + 1], p[head]) <= getdown(p[head + 1], p[head]) * w[j])head++; dp[i][j] = getdp(i, j, p[head]); while (head + 1 < tail && getup(i, p[tail - 1], p[tail - 2]) * getdown(j, p[tail - 1]) > getup(i, j, p[tail - 1]) * getdown(p[tail - 1], p[tail - 2])) tail--; p[tail++] = j; } } output(dp[k][n]); puts(""); #ifndef ONLINE_JUDGE cout << " :" << 1.0 * (clock() - prostart) / CLOCKS_PER_SEC << endl; #endif return 0; }

좋은 웹페이지 즐겨찾기