hdu5681 zxa and wifi
2016-05-31 22:11
465 查看
这道题目是不太好想的,尽管很容易看出来应该是dp,但是状态转移总觉得无从下手。
其实我们可以将状态分层,比如设$dp(i, j)$为用$i$个路由器覆盖前$j$个点所需的最小代价
我们先不考虑状态,而是考虑在每个位置上的决策对状态的影响,考虑在位置j的决策
1.如果在此处放置网线,有$dp(i, j) = min(dp(i, j), dp(i, j - 1) + b(i))$
2.如果在此处放置路由器,有$dp(i, r(j)) = min(dp(i, r(j)), dp(i - 1, l(j) - 1) + a(i))$
当然此处可以什么都不放,但是这种决策对状态没有影响,因此我们不考虑它。
$[l(i), r(i)]$表示$i$位置路由器的覆盖区间
注意到固定$i$,$dp(i, j)$应该是非降的,因此条件2的更新应该适用于所有$dp(i, k): k \leq r(j)$
用两重循环依次计算状态,用stl中的vector储存i位置满足$r(k) = i$的所有$k$,先用式2从后往前更新,再用式1从前往后更新即可
复杂度$O(n * max(k, log(n))$
代码如下:
View Code
其实我们可以将状态分层,比如设$dp(i, j)$为用$i$个路由器覆盖前$j$个点所需的最小代价
我们先不考虑状态,而是考虑在每个位置上的决策对状态的影响,考虑在位置j的决策
1.如果在此处放置网线,有$dp(i, j) = min(dp(i, j), dp(i, j - 1) + b(i))$
2.如果在此处放置路由器,有$dp(i, r(j)) = min(dp(i, r(j)), dp(i - 1, l(j) - 1) + a(i))$
当然此处可以什么都不放,但是这种决策对状态没有影响,因此我们不考虑它。
$[l(i), r(i)]$表示$i$位置路由器的覆盖区间
注意到固定$i$,$dp(i, j)$应该是非降的,因此条件2的更新应该适用于所有$dp(i, k): k \leq r(j)$
用两重循环依次计算状态,用stl中的vector储存i位置满足$r(k) = i$的所有$k$,先用式2从后往前更新,再用式1从前往后更新即可
复杂度$O(n * max(k, log(n))$
代码如下:
#include <algorithm> #include <cstdio> #include <cstring> #include <string> #include <queue> #include <map> #include <set> #include <ctime> #include <iostream> using namespace std; typedef long long ll; const int int_inf = 0x3f3f3f3f; const ll ll_inf = (ll)1 << 62; const int mod = 1e9 + 7; const double double_inf = 1e30; typedef unsigned long long ul; #define max(a, b) ((a) > (b) ? (a) : (b)) #define min(a, b) ((a) < (b) ? (a) : (b)) #define mp make_pair #define st first #define nd second #define lson (u << 1) #define rson (u << 1 | 1) #define pii pair<int, int> #define pb push_back #define type(x) __typeof(x.begin()) #define foreach(i, j) for(type(j)i = j.begin(); i != j.end(); i++) #define FOR(i, s, t) for(int i = s; i <= t; i++) #define ROF(i, t, s) for(int i = t; i >= s; i--) #define dbg(x) cout << x << endl #define dbg2(x, y) cout << x << " " << y << endl #define clr(x, i) memset(x, (i), sizeof(x)) #define maximize(x, y) x = max((x), (y)) #define minimize(x, y) x = min((x), (y)) inline int readint(){ bool neg = 0; char ch, t[11]; int k = 0; while((ch = getchar()) == ' ' || ch == '\n') ; neg = ch == '-'; ch == '-' ? neg = 1 : t[k++] = ch; while((ch = getchar()) >= '0' && ch <= '9') t[k++] = ch; int x = 0, y = 1; while(k) x += (t[--k] - '0') * y, y *= 10; return neg ? -x : x; } inline int readstr(char *s){ char ch; int len = 0; while((ch = getchar()) == ' ' || ch == '\n') ; *(s++) = ch, ++len; while((ch = getchar()) != ' ' && ch != '\n') *(s++) = ch, ++len; *s = '\0'; return len; } inline void writestr(const char *s){ while(*s != '\0') putchar(*(s++)); putchar('\n'); } inline int add(int x, int y){ if(x < 0) x += mod; if(y < 0) y += mod; return (x + y) % mod; } inline int mult(int x, int y){ if(x < 0) x += mod; if(y < 0) y += mod; ll tem = (ll)x * y; return tem % mod; } int debug = 0; //------------------------------------------------------------------------- const int maxn = 2e4 + 10; int a[maxn], x[maxn], b[maxn], d[maxn]; ll dp[105][maxn]; vector<int> c[maxn]; int l[maxn], r[maxn]; int n, k; //------------------------------------------------------------------------- ll solve(){ d[0] = d[1] = 0; FOR(i, 2, n) d[i] += d[i - 1]; FOR(i, 0, maxn - 1) c[i].clear(); FOR(i, 1, n){ int len = x[i]; int L = 0, R = i; while(R - L > 1){ int mid = (R + L) >> 1; if(d[i] - d[mid] <= len) R = mid; else L = mid; } l[i] = R; L = i, R = n + 1; while(R - L > 1){ int mid = (R + L) >> 1; if(d[mid] - d[i] <= len) L = mid; else R = mid; } r[i] = L; c[L].pb(i); } dp[0][0] = 0; FOR(i, 1, n) dp[0][i] = dp[0][i - 1] + b[i]; FOR(i, 1, k){ dp[i][n + 1] = ll_inf; ROF(j, n, 1){ int sz = c[j].size(); dp[i][j] = dp[i][j + 1]; FOR(u, 0, sz - 1) minimize(dp[i][j], dp[i - 1][l[c[j][u]] - 1] + a[c[j][u]]); } dp[i][0] = 0; FOR(j, 1, n) minimize(dp[i][j], dp[i][j - 1] + b[j]); } ll ans = dp[0] ; FOR(i, 1, k) minimize(ans, dp[i] ); return ans; } int main(){ /////////////////////////////////////////////////////////////////////////////////////////////////////////////// if(debug) freopen("in.txt", "r", stdin); int T = readint(); while(T--){ n = readint(); k = readint(); FOR(i, 1, n - 1) d[i + 1] = readint(); FOR(i, 1, n) a[i] = readint(), x[i] = readint(), b[i] = readint(); ll ans = solve(); printf("%lld\n", ans); } ////////////////////////////////////////////////////////////////////////////////////////////////////////////// return 0; }
View Code
相关文章推荐
- HTML+CSS+JAVASCRIPT基础复习题
- 可能是安装wget最简单的方式
- 马儿可夫之家
- 【Java】从源码分析动态代理机制
- 表排序(思路二)
- Android中的属性动画(一般属性动画,组合属性动画,AnimatorSet,动画监听)
- 32 Longest Valid Parentheses
- 树的子结构19
- 南邮java实验一—综合图形界面程序设计
- C++经验(一)
- 第二阶段冲刺第五天
- 关于U3D画面出现卡顿的问题
- [Java 基础]sun.misc.Unsafe
- 闭包
- spring基于@ExceptionHandler的异常处理
- 2015.05.31
- 测试点滴大搬家
- 四舍五入函数
- PopupWindowDemo
- 【C++ 学习】02 符号的十八般武艺