[HDOJ5543]Pick The Sticks(DP,01背包)
2024-08-24 04:15:11
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5543
题意:往长为L的线段上覆盖线段,要求:要么这些线段都在L的线段上,要么有不超过自身长度一半的部分在线段外面,最多有两条这样的线段(在两头)。
dp(i,j,k)表示前i个线段覆盖在长度为j的线段上,期中有k个线段不完全在这个线段上的最大价值。考虑线段长度的奇偶问题,所以事先把L和其他线段长度乘2,以便操作。所以枚举所有线段,一般情况,就是01背包的问题,dp(i,j,k)=max(dp(i,j,k), dp(i-1,j-w(i),k)+v(i))。当枚举到k不是0的时候,还需要更新两端放的情况:dp(i,j,k)=max(dp(i,j,k),dp(i-1,j-w(i)/2,k-1)+v(i))。直接取w(i)/2是没有关系的,因为我们在这里希望可以贪心地尽可能地少占用当前L上的长度。
还有一个trick:L=1的时候这么搞。这时L当成一个支点,只能放一个。所以要提前处理所有线段的最大价值。
#include <bits/stdc++.h>
using namespace std; typedef long long LL;
const int maxn = ;
int w[maxn], v[maxn];
int n, L;
LL dp[maxn][];
LL ret; int main() {
freopen("in", "r", stdin);
int T, _ = ;
scanf("%d", &T);
while(T--) {
scanf("%d %d", &n, &L);
memset(dp, , sizeof(dp));
ret = ; L <<= ;
for(int i = ; i <= n; i++) {
scanf("%d %d", &w[i], &v[i]);
w[i] <<= ;
ret = max(ret, (LL)v[i]);
}
for(int i = ; i <= n; i++) {
for(int j = L; j >= w[i]/; j--) {
for(int k = ; k <= ; k++) {
if(j >= w[i]) dp[j][k] = max(dp[j][k], dp[j-w[i]][k]+v[i]);
if(k) dp[j][k] = max(dp[j][k], dp[j-w[i]/][k-]+v[i]);
ret = max(ret, dp[j][k]);
}
}
}
printf("Case #%d: %lld\n", _++, ret);
}
return ;
}
最新文章
- struts之动态方法调用使用通配符
- 为什么学习Ruby On Rails:
- normal.1
- myeclipse里装svn插件
- html input readonly 和 disable的区别
- java.io.FileNotFoundException: class path resource [META-INF/xfire/services.xml] cannot be opened because it does not exist
- web安全:xss &;&; csrf
- Reporting Service部署之访问权限
- python_如何进行反向迭代和实现反向迭代?
- CSS3动画详解(超详细)
- linux添加zabbix service并开机自动启动
- jzoj5929. 【NOIP2018模拟10.26】情书
- *C#(WPF)--矩阵拖动和矩阵动画(拖动展开,不足动画效果)
- react-redux的mapStateToProps可取到state值但不会注入props
- Remove Duplicates from Sorted Array II leetcode java
- Gson转换时,Double转式化
- [翻译] M13ProgressSuite
- Linux 网络编程实例
- backbone.js 学习笔记
- React 入门实例教程[阮一峰的网络日志] (分享)