博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
poj1015
阅读量:5914 次
发布时间:2019-06-19

本文共 2630 字,大约阅读时间需要 8 分钟。

题意:从n个人中选出m个,每个人有固定的p值,d值,要求使m个人的p总和和d总和的差的绝对值最小,若有多解则取两者和最大的。

分析:dp

本题为special judge,不需要考虑多解情况。

f[i][j]表示在选m个人中的第i个人的时候使所有已选中的人的p,d差为j时,所能获得的p,d最大和。

f[i + 1][j + p[k] - d[k]] = f[i][j] + p[k] + d[k];(要求k之前没有选过,要查看f[i][j]的完整路径,确保无k)

填写完成后,观察f[m]找到最小差值,最大和。知道和差自然可以求出总的p,d。

也可以用另一种方法:

三维f[i,j,k]表示前i取j差值为k的最大和

f[i,j,k]=max{f[i-1,j,k],f[i-1,j-1,k-s1[i]]+s2[i]}

View Code
#include 
#include
#include
#include
#include
usingnamespace std; #define maxn 205 #define maxm 25 int n, m, w; int f[maxm][maxn *10]; int p[maxn], d[maxn]; int path[maxm][maxn *10]; bool vis[maxn]; int stk[maxn]; void input() {
for (int i =0; i < n; i++) scanf("%d%d", &p[i], &d[i]); } void getpath(int i, int j) {
memset(vis, 0, sizeof(vis)); while (path[i][j] !=-1) {
int k = path[i][j]; vis[k] =true; i--; j -= p[k] - d[k]; } } void make(int i, int j, int k) {
int a = p[k] + d[k]; int b = p[k] - d[k]; if (f[i +1][j + b] ==-1|| f[i +1][j + b] < f[i][j] + a) {
f[i +1][j + b] = f[i][j] + a; path[i +1][j + b] = k; return; } } void work() {
w = m *20; memset(f, -1, sizeof(f)); memset(path, -1, sizeof(path)); f[0][w] =0; for (int i =0; i < m; i++) for (int j =0; j <=2* w; j++) if (f[i][j] !=-1) {
getpath(i, j); for (int k =0; k < n; k++) if (!vis[k]) make(i, j, k); } int d1 =-1, d2 =-1, dd; for (int i =0; i <= w; i++) if (f[m][w + i] !=-1) {
d1 = i; break; } for (int i =0; i <= w; i++) if (f[m][w - i] !=-1) {
d2 = i; break; } if (d1 ==-1|| (d2 < d1 && d2 !=-1)) dd = w - d2; elseif (d2 ==-1|| (d1 < d2 && d1 !=-1)) dd = w + d1; elseif (f[m][w + d1] > f[m][w - d2]) dd = w + d1; else dd = w - d2; int a = f[m][dd]; int b = dd - w; int ansp = (a + b) /2; int ansd = (a - b) /2; printf("Best jury has value %d for prosecution and value %d for defence:\n", ansp, ansd); int top =0; a = m; b = dd; while (path[a][b] !=-1) {
int k = path[a][b]; stk[top++] = k; a--; b -= p[k] - d[k]; } sort(stk, stk + top); for (int i =0; i < top; i++) printf(" %d", stk[i] +1); putchar('\n'); putchar('\n'); } int main() {
//freopen("t.txt", "r", stdin); int t =0; while (scanf("%d%d", &n, &m), n | m) {
t++; printf("Jury #%d\n", t); input(); work(); } return0; }

转载地址:http://sygpx.baihongyu.com/

你可能感兴趣的文章
ELK采集之nginx 日志高德地图出城市IP分布图
查看>>
第二次作业
查看>>
Jquery下Ajax与PHP数据交换
查看>>
将博客搬至CSDN
查看>>
opencv 实现图像像素点反转
查看>>
Access denied for user 'root'@'localhost' (using p
查看>>
linux中grep命令
查看>>
H3C模拟器 DHCP Snooping 、中继 实例配置
查看>>
以太坊构建DApps系列教程(二):构建TNS代币
查看>>
sed工具的使用
查看>>
数据仓库工程师、大数据开发工程师、BI工程师、ETL工程师之间有什么区别?...
查看>>
JVM初识-java类加载器
查看>>
对比各类分布式锁缺陷,抓住Redis分布式锁实现命门
查看>>
初出茅庐的程序员该如何准备面试?【备战春招/秋招系列】
查看>>
ThinkSNS+ 基于 Laravel master 分支,从 1 到 0,再到 0.1
查看>>
设置typeid后织梦currentstyle 不起作用的修复方法
查看>>
AndroidManifest.xml解析
查看>>
Oracle技术沙龙:《列存数据库的崛起》
查看>>
Oracle技术之ASM Buffer Cache的作用和功能
查看>>
Oracle RAC failover测试
查看>>