Subset Sums 集合
对于从1到N 的连续整集合合,能划分成两个子集合,且保证每个集合的数字和是相等的.
举个例子,如果 N=3,对于{1,2,3}能划分成两个子集合,他们每个的所有数字和是相等的:
{3} and {1,2}
这是唯一一种分发(交换集合位置被认为是同一种划分方案,因此不会增加划分方案总数)
如果 N=7,有四种方法能划分集合{1,2,3,4,5,6,7},每一种分发的子集合各数字和是相等的:
{1,6,7} and {2,3,4,5} {注 1+6+7=2+3+4+5}
{2,5,7} and {1,3,4,6}
{3,4,7} and {1,2,5,6}
{1,2,4,7} and {3,5,6}
给出 N,你的程序应该输出划分方案总数,如果不存在这样的划分方案,则输出 0.程序不能预存结果
直接输出.
PROGRAM NAME: subset
INPUT FORMAT
输入文件只有一行,且只有一个整数 N
SAMPLE INPUT (file subset.in)
7
OUTPUT FORMAT
输出划分方案总数,如果不存在则输出 0.
SAMPLE OUTPUT (file subset.out)
4
===================================
对动规还不着么熟悉..需要在后来加强点..
=======================
骗分的搜索
还有一半不知如何剪枝
--------------
{
ID:jie19952
PROG:subset
LANG:PASCAL
}
var
n:longint;
bool:array[1..39]of boolean;
tot_aim:longint;
ans:longint;
procedure init;
begin
assign(input,'subset.in');
assign(output,'subset.out');
reset(input); rewrite(output);
end;
procedure terminate;
begin
close(input); close(output);
halt;
end;
procedure dfs(last,tot:longint);
var
i:longint;
begin
if (tot=tot_aim) then
begin
inc(ans);
exit;
end;
for i:=last-1 downto 1 do
if bool[i] then
begin
if tot+i<=tot_aim then
begin
bool[i]:=false;
dfs(i,tot+i);
bool[i]:=true;
end;
end;
end;
procedure main;
begin
readln(n);
fillchar(bool,sizeof(bool),true);
tot_aim:=((1+n)*n) div 4;
//t1:=(n+1) div 2;
ans:=0;
dfs(n+1,0);
writeln(ans div 2);
end;
begin
init;
main;
terminate;
end.
-------------------------
DP
0/1背包
--------------
{
ID:jie19952
PROG:subset
LANG:PASCAL
}
var
n:longint;
a_aim:longint;
f:array[0..390]of int64;
procedure init;
begin
assign(input,'subset.in');
assign(output,'subset.out');
reset(input); rewrite(output);
end;
procedure terminate;
begin
close(input); close(output);
halt;
end;
procedure main;
var
i,j,k:longint;
ans:longint;
begin
readln(n);
a_aim:=((1+n)*n) div 2;
if a_aim mod 2 =0 then
begin
a_aim:=a_aim div 2;
fillchar(f,sizeof(f),0);
f[0]:=1;
for i:=1 to n do
for j:=a_aim downto 0 do
if j>=i then f[j]:=f[j]+f[j-i];
writeln(f[a_aim] div 2);
end
else writeln('0');
end;
begin
init;
main;
terminate;
end.