您的位置:首页 > 其它

HDU 5681:zxa and wifi

2016-05-18 19:43 363 查看


zxa and wifi

 
 Accepts: 13
 
 Submissions: 299

 Time Limit: 2000/1000 MS (Java/Others)
 
 Memory Limit: 65536/65536 K (Java/Others)

问题描述
zxa来到Q镇做义工,镇长希望给住在Q镇中轴线上的nn户人家实现网络覆盖。这nn户人家可以看作是中轴线上的质点,从东到西依次编号从11到nn,其中第i(1\leq i < n)i(1≤i<n)户人家到第(i+1)(i+1)户人家的距离为d_id​i​​。

zxa负责了这个项目的方案设计,他获悉运营商给出了两种架设网络的方式。一种是花费a_ia​i​​的费用在第i(1\leq i\leq n)i(1≤i≤n)户人家安装无线路由器和相关网线使得距离第ii户人家不超过r_ir​i​​的人家(包括第ii户人家)都能上网。另一种是花费b_ib​i​​的费用为第i(1\leq i\leq n)i(1≤i≤n)户人家接通光缆使得该户人家能上网。

zxa很好奇,如果镇上为了防止无线电的辐射过大而至多只能在kk户人家架设无线路由,那么使得这nn户人家都能上网的最小花费是多少,你能帮助他吗?

输入描述
第一行有一个正整数TT,表示有TT组数据。

对于每组数据:

第一行有两个整数nn和kk。

第二行有(n-1)(n−1)个正整数,表示d_1,d_2,\cdots,d_{n-1}d​1​​,d​2​​,⋯,d​n−1​​。

接下来nn行,第i(1\leq i\leq n)i(1≤i≤n)行有三个正整数a_i,r_ia​i​​,r​i​​和b_ib​i​​。

每一行相邻数字之间只有一个空格。

1\leq T\leq 100,2\leq n\leq 2\cdot10^4,1\leq k\leq\min(n, 100),1\leq a_i,b_i,d_i,r_i\leq 10^5,1\leq\sum{n}\leq10^51≤T≤100,2≤n≤2⋅10​4​​,1≤k≤min(n,100),1≤a​i​​,b​i​​,d​i​​,r​i​​≤10​5​​,1≤∑n≤10​5​​

输出描述
对于每组数据,输出一行,包含一个正整数,表示使得这nn户人家都能上网的最小花费。

输入样例
2
2 1
1
12 11 3
1 7 4
5 5
7 4 8 6
13 6 3
14 2 3
3 6 4
11 12 2
9 14 4

输出样例
1
12

Hint
对于第二组样例,zxa在33号人家安装无线路由器,在11号、44号、55号人家接通光缆,这样的总代价是3+3+2+4=123+3+2+4=12。


首先二分得到每一个路由器作用的范围。

dp[i][k]表示使用k个路由器覆盖前i个点所需要的最小代价。

不使用路由器覆盖第i个点的话,有 dp[i][k]=dp[i][k-1]+b[i]

如果使用路由器覆盖第i个点,则直接枚举路由器那些端点在第i个点,然后找dp[le[id]][k-1]到dp[i][k-1]的最小值,使用一个队列维护这个最小值,二分查找。

代码:

#pragma warning(disable:4996)
#include <fstream>
#include <iostream>
#include <functional>
#include <algorithm>
#include <cstring>
#include <vector>
#include <string>
#include <cstdio>
#include <cmath>
#include <queue>
#include <stack>
#include <deque>
#include <set>
#include <map>
using namespace std;
typedef long long ll;

#define INF 0x33ffffff
#define mem(a, b) memset(a, b, sizeof(a))
#define pper(i,n,m) for(int i = n;i >= m; i--)
#define repp(i, n, m) for (int i = n; i <= m; i++)
#define rep(i, n, m) for (int i = n; i < m; i++)
#define sa(n) scanf("%d", &(n))
#define mp make_pair
#define ff first
#define ss second
#define pb push_back

const int maxn = 5e4 + 5;
const ll mod = 1e9 + 7;
const double PI = acos(-1.0);

struct ed
{
int to;
int next;
}edge[maxn];

int n, kth, edgen;
int a[maxn], r[maxn], b[maxn], d[maxn];
int head[maxn], que[maxn], le[maxn], ri[maxn], dp[maxn][110];

void add(int u, int v)
{
edgen++;
edge[edgen].to = v;
edge[edgen].next = head[u];
head[u] = edgen;
}

void init()
{
edgen = 0;
memset(head, -1, sizeof(head));
memset(edge, -1, sizeof(edge));
}

void solve()
{
int i, j, k, h;
sa(n), sa(kth);
repp(i, 2, n)
{
sa(d[i]);
d[i] = d[i - 1] + d[i];
}
repp(i, 1, n)
{
sa(a[i]), sa(r[i]), sa(b[i]);
}
repp(i, 1, n)
{
int pos1 = lower_bound(d + 1, d + n + 1, d[i] - r[i]) - d;
int pos2 = lower_bound(d + 1, d + n + 1, d[i] + r[i]) - (d + 1);
le[i] = pos1, ri[i] = pos2;
add(ri[i], i);
}
dp[0][0] = 0;
for (i = 1; i <= n; i++)
{
dp[i][0] = dp[i - 1][0] + b[i];
}
int res = dp
[0];
for (k = 1; k <= kth; k++)
{
int t = 1;
que[t] = 0;

for (i = 1; i <= n; i++)
{
dp[i][k] = dp[i - 1][k] + b[i];
for (h = head[i]; h != -1; h = edge[h].next)
{
int to = edge[h].to;
int pos = lower_bound(que + 1, que + t + 1, le[to] - 1) - que;
if (pos == t + 1)
continue;
dp[i][k] = min(dp[i][k], dp[que[pos]][k - 1] + a[to]);
}
while (t > 1 && dp[que[t]][k - 1] >= dp[i][k - 1])
{
t--;
}
t++;
que[t] = i;
}
res = min(res, dp
[k]);
}
printf("%d\n", res);
}

int main()
{
#ifndef ONLINE_JUDGE
freopen("i.txt", "r", stdin);
freopen("o.txt", "w", stdout);
#endif

int t;
sa(t);
while (t--)
{
init();
solve();
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: