fengyunfly吧 关注:9贴子:102
  • 2回复贴,共1

分组

收藏回复

  • 202.101.104.*
分组teams
Time Limit:1000MS  Memory Limit:65536K
Total Submit:2 Accepted:0 
Description 
你的任务是把一些人分成两组,使得: 
•每个人都被分到其中一组; 
•每个组都至少有一个人; 
•一组中的每个人都认识其他同组成员; 
•两组的成员人数近两接近。 
这个问题可能有多个解决方案,你只要输出任意一个即可,或者输出这样的分组法不存在。 
Input 
为了简单起见,所有的人都用一个整数标记,每个人号码不同,从1到N。 
第一行包括一个整数N(2≤N≤100),N就是需要分组的总人数;接下来的N行对应了这N个人,按每个人号码的升序排列,每一行给出了一串号码Aij(1≤Aij≤N,Aij≠i),代表了第i个人所认识的人的号码,号码之间用空格隔开,并以一个“0”结束。 
Output 
如果分组方法不存在,就输出信息“No solution”(输出时无需加引号);否则用两行输出分组方案;第一行先输出第一组的人数,然后给出第一组成员的号码,每个号码前有一个空格,同理给出第二组的信息。每组的成员号码顺序和组别顺序并不重要。
Sample Input 
5
2 3 5 0
1 4 5 3 0
1 2 5 0
1 2 3 0
4 3 2 1 0
Sample Output 
3 1 3 5
2 2 4




1楼2008-05-21 17:52回复
    program teams;
    var rest,alast,blast,which,c,d,e,f,g,h,i,j,k,m,n,now,amount:longint;
     finish,finish2:boolean;
     know:array[1.. 100,1.. 100] of boolean;
     use,re:array[1.. 100] of boolean;
     a,b,know2,disknow:array[1.. 100,0.. 100] of longint;
     number:array[1.. 100,1.. 2] of longint;
     sum:array[0.. 100,0.. 200] of boolean;
    begin
     assign(input,'river.in');
     reset(input);
     fillchar(use,sizeof(use),false);
     fillchar(know,sizeof(know),false);
     fillchar(know2,sizeof(know2),0);
     read(n);
     for i:=1 to n do begin
     know[i,i]:=true;
     end;
     for i:=1 to n do begin
     repeat
     read©;
     if c>0 then begin
     know[i,c]:=true;
     end;
     until c=0;
     for j:=1 to n do begin
     if not know[i,j] then begin
     inc(disknow[i,0]);
     disknow[i,disknow[i,0]]:=j;
     end;
     end;
     end;
     which:=0;
     repeat
     inc(which);
     finish:=true;
     for i:=1 to n do begin
     for j:=1 to n do begin
     if (not use[i]) and (not use[j]) and (not know[i,j]) then begin
     c:=i;
     d:=j;
     finish:=false;
     break;
     end;
     end;
     if not finish then break;
     end;
     if not finish then begin
     a[which,1]:=c;
     b[which,1]:=d;
     use[c]:=true;
     use[d]:=true;
     alast:=1;
     blast:=1;
     fillchar(re,sizeof(re),false);
     repeat
     finish2:=true;
     for i:=1 to alast do begin
     amount:=disknow[a[which,i],0];
     if amount>0 then begin
     for j:=1 to amount do begin
     now:=disknow[a[which,i],j];
     if not use[now] then begin
     re[now]:=true;
     finish2:=false;
     end;
     end;
     end;
     end;
     for i:=1 to blast do begin
     amount:=disknow[b[which,i],0];
     if amount>0 then begin
     for j:=1 to amount do begin
     now:=disknow[b[which,i],j];
     if not use[now] then begin
     if re[now] then begin
     writeln('no solution');
     halt;
     end
     else begin
     inc(alast);
     a[which,alast]:=now;
     use[now]:=true;
     finish2:=false;
     end;
     end;
     end;
     end;
     end;
     for i:=1 to n do begin
     if re[i] then begin
     inc(blast);
     b[which,blast]:=i;
     use[i]:=true;
     end;
     end;
     until finish2;
     number[which,1]:=alast;
     number[which,2]:=blast;
     end;
     until finish;
     rest:=n;
     for i:=1 to which do begin
     rest:=rest-number[which,1]-number[which,2];
     end;
     sum[0,0]:=true;
     for k:=1 to which do begin
     for i:=n downto 0 do begin
     for j:=n downto 0 do begin
     if sum[i,j] then begin
     sum[i+number[k,1],j+number[k,2]]:=true;
     sum[i+number[k,2],j+number[k,1]]:=true;
     end;
     end;
     end;
     end;
     {writeln(sum[2,1]);}
     for k:=0 to n do begin
     for i:=1 to n do begin
     if sum[i,i+k] then begin
     if k>=rest then begin
     writeln(i+rest);
     writeln(k);
     end
     else begin
     if (n div 2=0) then begin
     writeln(n div 2);
     writeln(n div 2);
     end
     else begin
     writeln((n+1) div 2);
     writeln(n-((n+1) div 2));
     end;
     end;
     halt;
     end;
     end;
     end;
     close(input);
    end.


    IP属地:上海禁言 |2楼2008-05-21 21:43
    回复
      膜拜!至今不会


      IP属地:美国禁言 |3楼2011-09-14 01:07
      回复