<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	
	>
<channel>
	<title>
	Comments on: 陪审团的筛选	</title>
	<atom:link href="https://ssmax.net/archives/11.html/feed" rel="self" type="application/rss+xml" />
	<link>https://ssmax.net/archives/11.html</link>
	<description>ssmax blog here~</description>
	<lastBuildDate>Fri, 06 Jan 2006 03:04:54 +0000</lastBuildDate>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.8.2</generator>
	<item>
		<title>
		By: ssmax		</title>
		<link>https://ssmax.net/archives/11.html/comment-page-1#comment-9</link>

		<dc:creator><![CDATA[ssmax]]></dc:creator>
		<pubDate>Fri, 06 Jan 2006 03:04:54 +0000</pubDate>
		<guid isPermaLink="false">http://blog.ssmax.net/archives/11.html#comment-9</guid>

					<description><![CDATA[然后贴一个鬼佬的思路：

Hi, I soved this problem. The program ran about 0.422 sec and used 768 kb , but there are people who solved it 0.050 - 0.110.How is it possible?  
Here is my solution: 
Let diff[i]=d[i]-p[i], sum[i]=d[i]+p[i], then the problem is to choose numbers p[1]..p[m] : 
p[i] belongs 1..n 
p[i]&lt;&gt;p[j] for i&lt;&gt;j; 
(s1=diff[p[1]]+diff[p[2]]+...diff[p[m]])==min; 
And when there are many numbers that minimize &#124;s1&#124; , then choose the one which maximizes s2=sum[p[1]]+sum[p[2]]+..sum[p[m]]. 
I used such DP interpretation: 
It&#039;s trivial to solve the problem for m=1. 
If there is a solution for m=k, then we can build the solution for m=k+1 using procedure: 
Let the solution for m=k be saved in an array A[i][j], where A[i][j] shows whether it&#039;s possible to choose k candidates from the first i candidates that s1=j, and if it&#039;s possible then C[i][j] shows s2. 
Then we can build an arrays B[i][j], D[i][j] for k+1 (which have the same function as A[i][j], C[i][j] for k): 
Code: 
for i=1 to n do 
 for j=&lt; minimum possible sum&gt; to &lt;maximum possible sum&gt; do 
 { 
      B[i][j]=B[i-1][j]; // do not include candidate number i 
      D[i][j]=D[i-1][j]; 
      if(A[i][j-diff[i]]) 
        if( (not B[i][j]) or (D[i][j]&lt;C[i][j-diff[i]]+sum[i])) 
        {  // include candidate number i 
               B[i][j]=A[i][j-diff[i]]; 
               D[i][j]=C[i][j-diff[i]]+sum[i]; 
        } 
 } 

So, we can build an arrays A[i][j], C[i][j] for any m. 
The first j&gt;=0 for which (A[n][j] or A[n][-j]) == true is the minimum value for &#124;s1&#124;. 
To get chosen candidates, on each stage save whether a candidate was included or not. 
Then just make a recursion descent. 
I very accuratly implemented the algorithm ( using binary array to save whether a candidate was included or not), but the program is very slow. 
Is it due to algorithm or implementation?]]></description>
			<content:encoded><![CDATA[<p>然后贴一个鬼佬的思路：</p>
<p>Hi, I soved this problem. The program ran about 0.422 sec and used 768 kb , but there are people who solved it 0.050 &#8211; 0.110.How is it possible?<br />
Here is my solution:<br />
Let diff[i]=d[i]-p[i], sum[i]=d[i]+p[i], then the problem is to choose numbers p[1]..p[m] :<br />
p[i] belongs 1..n<br />
p[i]<>p[j] for i<>j;<br />
(s1=diff[p[1]]+diff[p[2]]+&#8230;diff[p[m]])==min;<br />
And when there are many numbers that minimize |s1| , then choose the one which maximizes s2=sum[p[1]]+sum[p[2]]+..sum[p[m]].<br />
I used such DP interpretation:<br />
It&#8217;s trivial to solve the problem for m=1.<br />
If there is a solution for m=k, then we can build the solution for m=k+1 using procedure:<br />
Let the solution for m=k be saved in an array A[i][j], where A[i][j] shows whether it&#8217;s possible to choose k candidates from the first i candidates that s1=j, and if it&#8217;s possible then C[i][j] shows s2.<br />
Then we can build an arrays B[i][j], D[i][j] for k+1 (which have the same function as A[i][j], C[i][j] for k):<br />
Code:<br />
for i=1 to n do<br />
 for j=< minimum possible sum> to <maximum possible sum> do<br />
 {<br />
      B[i][j]=B[i-1][j]; // do not include candidate number i<br />
      D[i][j]=D[i-1][j];<br />
      if(A[i][j-diff[i]])<br />
        if( (not B[i][j]) or (D[i][j]<C[i][j-diff[i]]+sum[i])) 
        {  // include candidate number i 
               B[i][j]=A[i][j-diff[i]]; 
               D[i][j]=C[i][j-diff[i]]+sum[i]; 
        } 
 } 

So, we can build an arrays A[i][j], C[i][j] for any m. 
The first j>=0 for which (A[n][j] or A[n][-j]) == true is the minimum value for |s1|.<br />
To get chosen candidates, on each stage save whether a candidate was included or not.<br />
Then just make a recursion descent.<br />
I very accuratly implemented the algorithm ( using binary array to save whether a candidate was included or not), but the program is very slow.<br />
Is it due to algorithm or implementation?</maximum></p>
]]></content:encoded>
		
			</item>
		<item>
		<title>
		By: ssmax		</title>
		<link>https://ssmax.net/archives/11.html/comment-page-1#comment-8</link>

		<dc:creator><![CDATA[ssmax]]></dc:creator>
		<pubDate>Fri, 06 Jan 2006 03:03:18 +0000</pubDate>
		<guid isPermaLink="false">http://blog.ssmax.net/archives/11.html#comment-8</guid>

					<description><![CDATA[动态规划：
动态规划的基础：局部最优?整体最优

整体最优：
从M（给定）个候选人中选出N（给定）个，
得分差为X（给定）的，得分和最高的组合

局部最优：
从m（m&lt;=M）个候选人中选出n（n&lt;=N）个，
得分差为X（给定）的，得分和最高的组合

考虑到问题的规模——
选出的陪审团不超过20人，每人得分的范围是0到＋20
陪审团的得分差不超出【－400，＋400】
最多有801种可能

解这道题：
先用动态规划求出给定的得分差时，最高的得分和，
然后枚举出最小的得分差。

三维数组：
Map[i][j][k] 

第一维：参选人员
索引含义：M个候选人中的前i个
第二维：选出人数
索引含义：选出j个
第三维：得分差
索引含义：控辩双方得分差为k
数组元素：最优解决方案

1、将动态规划表中所有方案标记为“不存在”

2、植入种子,	标记map[0][0][0]存在，
      方案为谁也不选，得分和为0

假设从前m（给定）人中选出n（n&lt;=m,n&lt;=N）人，
得分差为X（所有可能值）的最优方案（得分和最高）
都已找出

则：
       FOR  i:=0 TO N-1 DO 
	FOR j:=min(X) TO max(X) DO
                 IF (map[m][i][j]+第m+1人)&gt;map[m][i+1][j+diff[m+1]]
	          THEN 
                          map[m][i+1][j+diff[m+1]]:=
                             map[m][i][j]+第m+1人;
	     //用已经存在的方案和第m+1个候选人组合新方案

注：diff[m+1]是第m+1个候选人的得分差

应选出的方案是
使map[M][N][i]存在,且i的绝对值最小的map[M][N][i]
如果map[M][N][+i] 和map[M][N][-i]都存在，
则选取两者中得分和较大的一个。

1、动态规划表的压缩存储
map[m][x][y]只在生成map[m+1][x][y]时有用
所以动态规划表中只用保留
第一维索引为m和m+1的数据

2、方案的存储
一个方案包括两个属性
1、候选人名单
2、得分和
当M=200时
候选人名单使用位集存储，
占用224bit(7个无符号长整形)

动态规划表占用的空间:2*21*801*8=269136字节(263k)]]></description>
			<content:encoded><![CDATA[<p>动态规划：<br />
动态规划的基础：局部最优?整体最优</p>
<p>整体最优：<br />
从M（给定）个候选人中选出N（给定）个，<br />
得分差为X（给定）的，得分和最高的组合</p>
<p>局部最优：<br />
从m（m<=M）个候选人中选出n（n<=N）个，
得分差为X（给定）的，得分和最高的组合

考虑到问题的规模——
选出的陪审团不超过20人，每人得分的范围是0到＋20
陪审团的得分差不超出【－400，＋400】
最多有801种可能

解这道题：
先用动态规划求出给定的得分差时，最高的得分和，
然后枚举出最小的得分差。

三维数组：
Map[i][j][k] 

第一维：参选人员
索引含义：M个候选人中的前i个
第二维：选出人数
索引含义：选出j个
第三维：得分差
索引含义：控辩双方得分差为k
数组元素：最优解决方案

1、将动态规划表中所有方案标记为“不存在”

2、植入种子,	标记map[0][0][0]存在，
      方案为谁也不选，得分和为0

假设从前m（给定）人中选出n（n<=m,n<=N）人，
得分差为X（所有可能值）的最优方案（得分和最高）
都已找出

则：
       FOR  i:=0 TO N-1 DO 
	FOR j:=min(X) TO max(X) DO
                 IF (map[m][i][j]+第m+1人)>map[m][i+1][j+diff[m+1]]<br />
	          THEN<br />
                          map[m][i+1][j+diff[m+1]]:=<br />
                             map[m][i][j]+第m+1人;<br />
	     //用已经存在的方案和第m+1个候选人组合新方案</p>
<p>注：diff[m+1]是第m+1个候选人的得分差</p>
<p>应选出的方案是<br />
使map[M][N][i]存在,且i的绝对值最小的map[M][N][i]<br />
如果map[M][N][+i] 和map[M][N][-i]都存在，<br />
则选取两者中得分和较大的一个。</p>
<p>1、动态规划表的压缩存储<br />
map[m][x][y]只在生成map[m+1][x][y]时有用<br />
所以动态规划表中只用保留<br />
第一维索引为m和m+1的数据</p>
<p>2、方案的存储<br />
一个方案包括两个属性<br />
1、候选人名单<br />
2、得分和<br />
当M=200时<br />
候选人名单使用位集存储，<br />
占用224bit(7个无符号长整形)</p>
<p>动态规划表占用的空间:2*21*801*8=269136字节(263k)</p>
]]></content:encoded>
		
			</item>
		<item>
		<title>
		By: ssmax		</title>
		<link>https://ssmax.net/archives/11.html/comment-page-1#comment-7</link>

		<dc:creator><![CDATA[ssmax]]></dc:creator>
		<pubDate>Fri, 06 Jan 2006 03:02:02 +0000</pubDate>
		<guid isPermaLink="false">http://blog.ssmax.net/archives/11.html#comment-7</guid>

					<description><![CDATA[简单的解法：
遍历所有的陪审团组合
对每个组合打分
记录最合要求的组合]]></description>
			<content:encoded><![CDATA[<p>简单的解法：<br />
遍历所有的陪审团组合<br />
对每个组合打分<br />
记录最合要求的组合</p>
]]></content:encoded>
		
			</item>
		<item>
		<title>
		By: ssmax		</title>
		<link>https://ssmax.net/archives/11.html/comment-page-1#comment-6</link>

		<dc:creator><![CDATA[ssmax]]></dc:creator>
		<pubDate>Fri, 06 Jan 2006 03:01:27 +0000</pubDate>
		<guid isPermaLink="false">http://blog.ssmax.net/archives/11.html#comment-6</guid>

					<description><![CDATA[抽象：
给定正数m,n（m&lt;=200,n&lt;=20），
和长度为m的两个数组p,d
满足0&lt;=p[i]&lt;=20, 0&lt;=d[i]&lt;=20

求序列1..m的一个n长的子序列S，
满足：
1、	∑p[Si]与∑d[Si]的差尽量小
2、	在满足1的前提下
	∑p[Si]与∑d[Si]的和尽量大
3、	当有多组解的时候，答任何一解都算对]]></description>
			<content:encoded><![CDATA[<p>抽象：<br />
给定正数m,n（m<=200,n<=20），
和长度为m的两个数组p,d
满足0<=p[i]<=20, 0<=d[i]<=20

求序列1..m的一个n长的子序列S，
满足：
1、	∑p[Si]与∑d[Si]的差尽量小
2、	在满足1的前提下
	∑p[Si]与∑d[Si]的和尽量大
3、	当有多组解的时候，答任何一解都算对
</p>
]]></content:encoded>
		
			</item>
	</channel>
</rss>
