POJ2454 Jersey Politics ——贪心+随机化算法——Pku2454

初看此题时,显然大家都想到了贪心+搜索+剪枝,但是POJ的评测机是很不给力的,一定是TLE。所以,理所当然的,我们知道了random的威力。

先证明一下贪心算法的正确性:

策略:将这n*3个元素倒序快排一下,取前n*2个元素分为两组,最后n个元素分为一组。

证明:如果不这样选的话,那么前两组的总和必会比这样选的情况小,那么更有可能失败。证毕。

随机化算法:

每次从前两个集合中各选一个元素进行交换,如果满足条件直接输出并halt.

这个随机化的证明嘛,我也不会。

CODE

Program POJ2454;//By_Poetshy

Const

	maxn=200;

Var

	i,j,k,m,n					:Longint;

	a,rank						:Array[1..maxn]of Longint;

	v							:Array[1..maxn]of Boolean;

	all,sum,temp				:Longint;



Procedure Qsort(l,r:Longint);

var i,j,k,temp:Longint;

begin

	i:=l;j:=r;k:=a[(i+j)>>1];

	repeat

		while a[i]>k do inc(i);

		while a[j]<k do dec(j);

		if i<=j then

			begin

				temp:=a[i];a[i]:=a[j];a[j]:=temp;

				temp:=rank[i];rank[i]:=rank[j];rank[j]:=temp;

				inc(i);dec(j);

			end;

	until i>j;

	if i<r then Qsort(i,r);

	if l<j then Qsort(l,j);

end;



Procedure Print;

var j:Longint;

begin

	for j:=1 to n do writeln(rank[j]);

	for j:=n+1 to n*2 do writeln(rank[j]);

	for j:=n*2+1 to n*3 do writeln(rank[j]);

end;



Function check:Boolean;

begin

	if sum<=500*n then exit(false);

	if all-sum<=500*n then exit(false);

	exit(true);

end;



BEGIN

	readln(n);

	for i:=1 to n*3 do

		begin

			readln(a[i]);rank[i]:=i;

		end;

	Qsort(1,n*3);

	sum:=0;m:=1;

	fillchar(v,sizeof(v),0);

	for i:=1 to n<<1 do inc(all,a[i]);

	for i:=1 to n do 

		begin

			inc(sum,a[i]);

			v[i]:=true;

		end;

	randomize;

	while true do 

		begin

			if Check then 

				begin

					Print;

					halt;

				end;

			i:=random(n)+1;

			j:=random(n)+n+1;

			inc(sum,a[j]);dec(sum,a[i]);

			temp:=a[i];a[i]:=a[j];a[j]:=temp;

			temp:=rank[i];rank[i]:=rank[j];rank[j]:=temp;

		end;

END.

你可能感兴趣的:(jersey)