当前位置: 首页 > news >正文

POJ1015 Jury Compromise(DP)

题意:

输入n组数据,选出m个,每组数据有一个D值和一个P值,要求输入|D-P|的和最小时的D和P和选取的数据下标,如果有相同的,输出|D+P|的和最大的那个。

要点:

真的很难这题,因为相同时要输出和最大的那个,所以我们状态转移方程不能只考虑差最小,而且要将k=|D-P|的和放入转移的量,用DP[i][j][k]表示前j个中选i个的差之和为k时|D+P|的和的最大值。因为k可以是负数,所以加上一个偏移量fix,而且k是没办法状态转移的,所以我们只能一个个搜并且标记,一开始d全为-1,更改后说明可以转移,边界值为d[0][j][fix] = 0,转移的时候一共两个决策:一种是不选当前的人,这样d[i][j][k]=d[i][j-1][k],等于他前一个的d值;如果选取当前的人,那么要判断选择此人前的d是否不为-1等。

网上有大神想出了二维数组的标准做法,就是d[i][k]说明已经选了i个人,差和为k的最大值,后面用j什么的取筛选。想法非常精妙,可惜是错误的,他的算法会出现如果值相同,路径随机选取的问题。discuss里有大牛发现并改进了,真是厉害。正确做法:点击打开链接


15554087Seasonal1015Accepted32640K641MSC++1748B2016-05-26 08:24:36
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<algorithm>
using namespace std;
struct node
{
	int d, p;
	int s, v;
}pre[205];
int d[25][205][810], path[25][205][810];

int main()
{
	int n, m, count = 0;
	int i, j, k;
	while (scanf("%d%d", &n, &m) != EOF)
	{
		if (n == 0 && m == 0)
			break;
		for (i = 1; i <= n; i++)
		{
			scanf("%d%d", &pre[i].p, &pre[i].d);
			pre[i].s = pre[i].p + pre[i].d;
			pre[i].v = pre[i].p - pre[i].d;
		}
		memset(d, -1, sizeof(d));
		memset(path, 0, sizeof(path));
		int fix = 20 * m;			//为了防止出现负数,加一个偏移量
		for (i = 0; i <= n; i++)
			d[0][i][fix] = 0;		//边界值,注意偏移量
		for (i = 1; i <= m; i++)
			for (j = i; j <= n;j++)
				for (k = 0; k <= 2 * fix;k++)
				{
					d[i][j][k] = d[i][j - 1][k];
					path[i][j][k] = path[i][j - 1][k];//决策一:不取当前的候选人,直接赋值与下一个比较,如果下一个大就更改,当前大就不用改
					if (k >= pre[j].v&&k - pre[j].v <= 2 * fix&&d[i - 1][j - 1][k - pre[j].v] >= 0 && d[i - 1][j - 1][k - pre[j].v] + pre[j].s >= d[i][j][k])
					{//决策二:取当前的候选人
						d[i][j][k] = d[i - 1][j - 1][k - pre[j].v] + pre[j].s;
						path[i][j][k] = j;//路径记录,说明选了当前点
					}
				}
		for (k = 0; k <= fix; k++)
			if (d[m][n][fix - k] >= 0 || d[m][n][fix + k] >= 0)//k为最小辩控差
				break;
		int div = d[m][n][fix - k] > d[m][n][fix + k] ? fix - k:fix + k;
		int D = (d[m][n][div] - div + fix) / 2;//辩方总值 = (辨控和+辨控差-修正值)/2    
		int P = (d[m][n][div] + div - fix) / 2;//控方总值 = (辨控和-辨控差+修正值)/2    
		printf("Jury #%d\n", ++count);
		printf("Best jury has value %d for prosecution and value %d for defence:\n", P, D);
		int ans[25];
		int c = path[m][n][div];
		for (i = div,k = m; k >= 1; k--)//选路径的时候已经是按从小到大了
		{
			ans[k] = c;
			i -= pre[c].v;
			c = path[k - 1][c - 1][i];
		}
		for (i = 1; i <= m; i++)
			printf(" %d", ans[i]);
		printf("\n\n");
	}
	return 0;
}


转载于:https://www.cnblogs.com/seasonal/p/10343733.html

相关文章:

  • React 的慢与快:优化 React 应用实战
  • required 引发的小小思考
  • Python cos() 函数
  • [数据结构] 冒泡排序
  • NIPT无创产前分析思路
  • xshell、putty远程连接
  • 利用GitHub Pages和Hexo搭建个人博客
  • 为什么Python发展得如此之快?
  • 程序员为什么要时刻保持危机感?
  • 高并发服务设计——缓存
  • 关于领域模型与技术架构的关系的思考
  • 学会容器服务帮你打造Docker云端最佳运行环境
  • ASP.NET中 ListView(列表视图)的使用前台绑定
  • 1507 酒厂选址
  • win10系统的简单优化
  • 【刷算法】求1+2+3+...+n
  • 2018一半小结一波
  • 5分钟即可掌握的前端高效利器:JavaScript 策略模式
  • android高仿小视频、应用锁、3种存储库、QQ小红点动画、仿支付宝图表等源码...
  • ES6--对象的扩展
  • iOS动画编程-View动画[ 1 ] 基础View动画
  • Iterator 和 for...of 循环
  • JAVA_NIO系列——Channel和Buffer详解
  • nfs客户端进程变D,延伸linux的lock
  • passportjs 源码分析
  • rabbitmq延迟消息示例
  • V4L2视频输入框架概述
  • 从零开始的webpack生活-0x009:FilesLoader装载文件
  • 第13期 DApp 榜单 :来,吃我这波安利
  • 聊聊spring cloud的LoadBalancerAutoConfiguration
  • 三栏布局总结
  • 深入体验bash on windows,在windows上搭建原生的linux开发环境,酷!
  • 手写双向链表LinkedList的几个常用功能
  • 微信小程序实战练习(仿五洲到家微信版)
  • 应用生命周期终极 DevOps 工具包
  • 远离DoS攻击 Windows Server 2016发布DNS政策
  • 在Docker Swarm上部署Apache Storm:第1部分
  • linux 淘宝开源监控工具tsar
  • 好程序员大数据教程Hadoop全分布安装(非HA)
  • ​用户画像从0到100的构建思路
  • ## 临床数据 两两比较 加显著性boxplot加显著性
  • #pragma multi_compile #pragma shader_feature
  • #控制台大学课堂点名问题_课堂随机点名
  • #我与Java虚拟机的故事#连载14:挑战高薪面试必看
  • %3cli%3e连接html页面,html+canvas实现屏幕截取
  • (01)ORB-SLAM2源码无死角解析-(66) BA优化(g2o)→闭环线程:Optimizer::GlobalBundleAdjustemnt→全局优化
  • (搬运以学习)flask 上下文的实现
  • (超详细)语音信号处理之特征提取
  • (五)网络优化与超参数选择--九五小庞
  • (转载)利用webkit抓取动态网页和链接
  • .bat批处理(五):遍历指定目录下资源文件并更新
  • .equals()到底是什么意思?
  • .locked1、locked勒索病毒解密方法|勒索病毒解决|勒索病毒恢复|数据库修复
  • .net Application的目录
  • .net core 6 使用注解自动注入实例,无需构造注入 autowrite4net