CDN流量调度问题
题意:
有n个线路,每个线路的任务量为a[i],初始状态下,每个线路起初只有一个节点,每个线路完成任务所需时间为
现在你要给每个线路增加节点,所有增加的节点总数不超过m,第i个线路增加节点不超过ti。
问完成所有任务最小的时间花费
题解:
分组背包
想想每个线路都有多种增加节点的可能,我们要在其中选择一个最优的,总容量为m。
对于每个线路,体积为ai,价值为所节省的时间ti,每组的物品数量不会超过sqrt(ai)。跑一个分组背包
注意:花费的时间为向上取整,很坑
代码:
// Problem: CDN流量调度问题
// Contest: HDOJ
// URL: https://acm.hdu.edu.cn/contests/contest_showproblem.php?pid=1003&cid=1029
// Memory Limit: 524 MB
// Time Limit: 6000 ms
//
// Powered by CP Editor (https://cpeditor.org)//#pragma GCC target("avx")
//#pragma GCC optimize(2)
//#pragma GCC optimize(3)
//#pragma GCC optimize("Ofast")
// created by myq
#include <algorithm>
#include <cctype>
#include <climits>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <list>
#include <map>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>
using namespace std;
typedef long long ll;
#define x first
#define y second
typedef pair<int, int> pii;
const int N= 400010;
const int mod= 998244353;
inline int read()
{int res= 0;int f= 1;char c= getchar();while (c > '9' || c < '0') {if (c == '-')f= -1;c= getchar();}while (c >= '0' && c <= '9') {res= (res << 3) + (res << 1) + c - '0';c= getchar();}return res;
}
int a[N];
int t[N];
int dp[10010], c[201][201], w[201][201];
int main()
{// ios::sync_with_stdio(0);// cin.tie(0);// cout.tie(0);int _;scanf("%d", &_);while (_--) {int n, m;scanf("%d%d", &n, &m);int now= 0;for (int i= 1; i <= n; i++) {scanf("%d", &a[i]);now+= a[i];}for (int i= 1; i <= n; i++)scanf("%d", &t[i]);for (int i= 1; i <= n; i++) {w[i][0]= 0;c[i][0]= 0;for (int j= 0; j <= t[i] - 1; j++) {int x= a[i] - ((a[i] + j) / (1 + j));if (x == w[i][w[i][0]])continue;else {w[i][++w[i][0]]= x;c[i][++c[i][0]]= j;}}}memset(dp, 0, sizeof dp);for (int i= 1; i <= n; i++) {for (int k= m; k >= 0; k--)for (int j= 1; j <= w[i][0]; j++) {if (k >= c[i][j])dp[k]= max(dp[k - c[i][j]] + w[i][j], dp[k]);elsebreak;}}int res= 0;for (int i= 0; i <= m; i++)res= max(res, dp[i]);printf("%d\n", now - res);}return 0;
}
/**
**/