题意略。

思路:

这个题目开始我本来打算用个二维dp,令dp[ i ][ j ]为考虑前i个人,有j个名额的时候,我所能获取的最小差,后来发现不好转移。因为dp[ i ][ j ]有可能是+2,

也有可能是-2,这两种值对我以后的求解可能都有用。后来想再添加一维,dp[ i ][ j ][ 0 ]表示正值的最小,dp[ i ][ j ][ 1 ]表示负值的最小(绝对值的最小)。

这样dp逻辑又很复杂。最后参考了网上的解法,于是将状态定义为:

dp[ i ][ j ][ k ]表示在前i个人里考虑,有j个名额,使得sigma(p) - sigma(d)为k时,我所能获得的sigma(p + d)的最大值。

状态转移方程:dp[ i ][ j ][ k ] = max(dp[i - 1][ j ][ k ] , dp[i - 1][j - 1][k - p[i] + d[i] ] + p[ i ] + d[ i ])

只可惜我做题时只想到了正负值的问题,没有更进一步将正负值直接确定为差值,然后dp对象为p + d,从而满足题目中的第二个条件。

有时dp对象可以是次要条件,而不是首要条件,换一种方向去思考问题。

内存很紧张

//#include<bits/stdc++.h>
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn1 = ;
const int maxn2 = ;
const int maxn3 = ;
const int mid = maxn3>>;
const int F = 0x3f;
const int INF = 0x3f3f3f3f; struct node{
int peo,place,sub;
node(int peo = ,int place = ,int sub = ){
this->peo = peo,this->place = place,this->sub = sub;
}
}; int p[maxn2],d[maxn2],dp[maxn2][maxn1][maxn3],store[maxn2],n,m;
node path[maxn2][maxn1][maxn3]; int main(){
int cas = ;
while(scanf("%d%d",&n,&m) == && (n + m)){
for(int i = ;i <= n;++i) scanf("%d%d",&p[i],&d[i]);
int total = * m;
int low = mid - total,up = mid + total; for(int i = ;i <= n;++i){
for(int j = ;j <= m;++j){
for(int k = low;k <= up;++k){
dp[i][j][k] = -;
path[i][j][k] = node(-,-,-);
}
}
} for(int i = ;i <= n;++i) dp[i][][mid] = ; for(int i = ;i <= n;++i){
int bound = min(i,m);
for(int j = ;j <= bound;++j){
for(int k = low;k <= up;++k){
int part1 = dp[i - ][j][k];
int part2 = (k - p[i] + d[i] < low || k - p[i] + d[i] > up || dp[i - ][j - ][k - p[i] + d[i]] == -) ? - : dp[i - ][j - ][k - p[i] + d[i]] + p[i] + d[i];
dp[i][j][k] = max(part1,part2);
if(part1 == - && part2 == -) continue;
if(part1 > part2) path[i][j][k] = node(i - ,j,k);
else path[i][j][k] = node(i - ,j - ,k - p[i] + d[i]);
}
}
}
int idx;
for(int i = ;i <= total;++i){
int lft = mid - i,rht = mid + i;
int maxx = max(dp[n][m][lft],dp[n][m][rht]);
if(maxx == -) continue;
if(maxx == dp[n][m][lft]) idx = lft;
else idx = rht;
if(maxx != -) break;
}
int tail = ;
for(int i = n,j = m,k = idx;i != -;){
node temp = path[i][j][k];
int nxti = temp.peo;
int nxtj = temp.place;
int nxtk = temp.sub;
if(nxti == -) break;
if(nxtj < j) store[tail++] = i;
i = nxti,j = nxtj,k = nxtk;
}
int ans1 = ,ans2 = ;
for(int i = ;i < tail;++i){
ans1 += p[store[i]];
ans2 += d[store[i]];
}
printf("Jury #%d\n",cas++);
printf("Best jury has value %d for prosecution and value %d for defence:\n",ans1,ans2);
for(int i = tail - ;i >= ;--i) printf(" %d",store[i]);
printf("\n\n");
}
return ;
} /*
4 2
1 2
2 3
4 1
6 2 10 5
3 8
15 8
11 8
7 8
1 8
17 8
8 8
2 8
13 8
3 8 5 3
13 11
3 17
15 20
6 13
17 9 8 5
3 5
17 16
6 0
17 10
6 14
3 19
4 13
0 17
*/

最新文章

  1. 从零构建JavaScript的对象系统
  2. LeetCode5:Longest Palindromic Substring
  3. django之form表单验证
  4. hdu 5727 Necklace dfs+二分图匹配
  5. rspec+rest-client测试第三方web service
  6. 一些常用的SQL查询语句
  7. [转载] 已知strcpy的函数原型:char *strcpy(char *strDest, const char *strSrc),编写函数 strcpy(C++版)
  8. 【英语】Bingo口语笔记(58) - blow系列
  9. skyline TerraBuilder 制作MPT方法与技巧(2)
  10. (转) Python in NetBeans IDE 8.0
  11. Mac下获取AppStore安装包文件路径-取出安装包
  12. 浅谈Linux ftp服务器相关配置
  13. linux文件系统下的特殊权限
  14. Unity UGUI基础之Button
  15. scrapy 爬取豆瓣互联网图书
  16. pyspark数据准备
  17. 运用PowerDesigner的反向工程,可以导入SQL脚本,从而生成物理模型
  18. 14.linux下复制粘贴
  19. WINDOWS内核版本
  20. Dalvik指令备忘

热门文章

  1. Windows 设置自启动计划任务(非登录启动)
  2. Python基础之格式化输出、运算符、数字与布尔值互换以及while...else
  3. linux初学者-swap分区篇
  4. JAVA 基于TCP协议的一对一,一对多文件传输实现
  5. 如何在jsp中显示数据库的内容
  6. Javaweb入门 数据库第二天
  7. Mybatis使用动态sql
  8. 这 3 个 Set 集合的实现有点简单,那来做个总结吧
  9. vscode vue开发环境搭建
  10. 【iOS】iOS 调试快速定位程序在哪崩溃