解题报告 poj 1486

 

1.        题目  POJ 1486

Description

Professor Clumsey is going to give an important talk this afternoon. Unfortunately, he is not a very tidy person and has put all his transparencies on one big heap. Before giving the talk, he has to sort the slides. Being a kind of minimalist, he wants to do this with the minimum amount of work possible.

The situation is like this. The slides all have numbers written on them according to their order in the talk. Since the slides lie on each other and are transparent, one cannot see on which slide each number is written.

 


Well, one cannot see on which slide a number is written, but one may deduce which numbers are written on which slides. If we label the slides which characters A, B, C, ... as in the figure above, it is obvious that D has number 3, B has number 1, C number 2 and A number 4.

Your task, should you choose to accept it, is to write a program that automates this process.

Input

The input consists of several heap descriptions. Each heap descriptions starts with a line containing a single integer n, the number of slides in the heap. The following n lines contain four integers xmin, xmax, ymin and ymax, each, the bounding coordinates of the slides. The slides will be labeled as A, B, C, ... in the order of the input.

This is followed by n lines containing two integers each, the x- and y-coordinates of the n numbers printed on the slides. The first coordinate pair will be for number 1, the next pair for 2, etc. No number will lie on a slide boundary.

The input is terminated by a heap description starting with n = 0, which should not be processed.

Output

For each heap description in the input first output its number. Then print a series of all the slides whose numbers can be uniquely determined from the input. Order the pairs by their letter identifier.

If no matchings can be determined from the input, just print the word none on a line by itself.

Output a blank line after each test case.

Sample Input

4
6 22 10 20
4 18 6 16
8 20 2 18
10 24 4 8
9 15
19 17
11 7
21 11
2
0 2 0 2
0 2 0 2
1 1
1 1
0

Sample Output

Heap 1
(A,4) (B,1) (C,2) (D,3)
 
Heap 2
none

Source

Southwestern European Regional Contest 1998

 

2.        题目实质

言简意赅地说,就是求二分图匹配的必须边。

3.        题目来源  poj

4.        算法

首先先跑一遍匈牙利算法,求二分图最大匹配,然后枚举着将匹配后的边删去,再接着跑匈牙利(也可用以匹配的边的一边进行增广,不能进行则是关键边),如果边数减少说明这是一个关键边,若果边数不减少说明不是,依此类推。

但是,匈牙利算法 NOIP 不考,于是乎,另一种就应运而生了。

遍历所有的矩形和数,看有没有一个矩形内只有一个数,或者一个数只属于一个矩形,这两种情况为可判断的情况,除这些之外的不确定,这个可用数学归纳法证明。然后每确定一种可确定的情况,就将这一个数和这一个矩形删去,依此类推。

5.        注意事项

第一种不好实现,第二种不太对还容易超时,恩恩。

6.        程序代码

第一种 Ray Pascal

program lonely;

  var

    max,n,time,ans,i,j:longint;

    x1,x2,x3,y1,y2,y3,match,anss:array[0..100] of longint;

    a:array[0..100,0..100] of boolean;

    v:array[0..100] of boolean;

    ff:boolean;

  function dfs(s:longint):boolean;

    var

      i:longint;

    begin

      for i:=1 to n do

        begin

          if (not v[i])and(a[i,s]) then

            begin

              v[i]:=true;

              if (match[i]=0)or(dfs(match[i])) then

                begin

                  match[i]:=s;

                  exit(true);

                end;

            end;

        end;

      exit(false);

    end;

  function can(i,j:longint):boolean;

    begin

      if (x3[j]>=x1[i])and(x3[j]<=x2[i])and(y3[j]>=y1[i])and(y3[j]<=y2[i]) then exit(true);

      exit(false);

    end;

  begin

    assign(input,'slides.in');

    reset(input);

    assign(output,'slides.out');

    rewrite(output);

    readln(n);

    for i:=1 to n do

      readln(x1[i],x2[i],y1[i],y2[i]);

    for i:=1 to n do

      readln(x3[i],y3[i]);

    fillchar(a,sizeof(a),false);

    fillchar(match,sizeof(match),0);

    ans:=0;

    for i:=1 to n do

      for j:=1 to n do

        begin

          if can(i,j) then a[i,j+n]:=true;

        end;

    for i:=n+1 to n+n do

      begin

        fillchar(v,sizeof(v),false);

        if dfs(i) then inc(ans);

      end;

    max:=ans;

    anss:=match;

    ff:=false;

    for i:=1 to n do

      begin

        if anss[i]<>0 then

          begin

            a[i,anss[i]]:=false;

            ans:=0;

            fillchar(match,sizeof(match),0);

            for j:=n+1 to n+n do

              begin

                fillchar(v,sizeof(v),false);

                if dfs(j) then inc(ans);

              end;

            if (ans<max) then

              begin

                writeln(chr(i+64),' ',anss[i]-n);

                ff:=true;

              end;

            a[i,anss[i]]:=true;

          end;

      end;

    if not ff then write('None');

    close(input);

    close(output);

  end.

 

第二种???(C++

#include<stdio.h>
#include<stdlib.h>
struct rectangle{
       int data;
       int xmax;
       int xmin;
       int ymin;
       int ymax;
       int app;
       };
struct dot{
       int isFound;
       int x;
       int y;
       int app;
       };
void readRect(struct rectangle rect[],int n);
void readDot(struct dot dot[],int n);
int FindRect(struct rectangle rect[],struct dot dot[],int n);//返回拥有唯一数的矩形下标,如果没有则返回0;顺带就把这个矩形的data赋值,数的belon赋值;一旦找到一个就立即返回退出.
int FindDot(struct rectangle rect[],struct dot dot[],int n);//返回只在一个矩形的数的下标,如果没有则返回0;顺带就把这个矩形的data赋值,数的belon赋值; 一旦找到一个就立即返回退出.
int dotIn(struct rectangle rect,struct dot dot);
int main()
{
    int n,i,j,order=0,flag;
    struct rectangle rect[27];//rect,dot都是从1开始使用
    struct dot dot[27];
    scanf("%d",&n);
    while(n!=0)
    {
               int temp1=-1,temp2;
               order++;
               flag=1;
               readRect(rect,n);
               readDot(dot,n);
                    for(i=1;i<=n;i++)
                    {
                                    
                                     if ((temp1=FindRect(rect,dot,n))==0&&(temp2=FindDot(rect,dot,n))==0) {
                                                                printf("Heap %d\nnone\n",order);
                                                                flag=0;
                                                                break;
                                                                }
                    }
                printf("temp1==%d,temp2==%d\n",temp1,temp2);
                if (flag==1){
                          printf("Heap %d\n",order);
                          for(i=1;i<=n;i++)
                          {
                                 if (rect[i].data!=0)
                                 printf("(%c,%d) ",'A'+i-1,rect[i].data);
                          }
                          printf("\n");
                          printf("\n");
                         }
                scanf("%d",&n);
    }
    system("pause");
    return 0;
}

void readRect(struct rectangle rect[],int n)
{
     int i;
     for(i=1;i<=n;i++)
     {
                      scanf("%d %d %d %d",&rect[i].xmin,&rect[i].xmax,&rect[i].ymin,&rect[i].ymax);
                      rect[i].data=0;
                      rect[i].app=0;
     }
}

void readDot(struct dot dot[],int n)
{
     int i;
     for(i=1;i<=n;i++)
     {
                      scanf("%d %d",&dot[i].x,&dot[i].y);
                      dot[i].isFound=0;
                      dot[i].app=0;
     }
}

int FindRect(struct rectangle rect[],struct dot dot[],int n)//返回拥有唯一数的矩形下标,如果没有则返回0;顺带就把这个矩形的data赋值,数的belon赋值;一旦找到一个就立即返回退出.
{
    int i,j;
    for(i=1;i<=n;i++)
    {
                     if (dot[i].isFound==0)
                     {
                                           int temp=0;
                                           dot[i].app=0;
                                           for(j=1;j<=n;j++)
                                           if ((rect[j].data==0)&&(dotIn(rect[j],dot[i])==1)){
                                                                                             dot[i].app++;
                                                                                             temp=j;
                                                                                             }
                                           if (dot[i].app==1) {
                                                       rect[temp].data=i;
                                                       dot[i].isFound=1;
                                                       return i;
                                                       }
                     }
    }
    return 0;
}

int FindDot(struct rectangle rect[],struct dot dot[],int n)
{
    int i,j;
    for(i=1;i<=n;i++)
    {
                     if (rect[i].data==0)
                     {
                                         int temp=0;
                                         rect[i].app=0;
                                         for(j=1;j<=n;j++)
                                         if ((dot[j].isFound==0)&&(dotIn(rect[i],dot[j])==1)){
                                                                                              rect[i].app++;
                                                                                              temp=j;
                                                                                              }
                                         if (rect[i].app==1) {
                                                             rect[i].data=temp;
                                                             dot[temp].isFound=1;
                                                             return i;
                                                             }
                     }
    }
    return 0;
}

int dotIn(struct rectangle rect,struct dot dot)
{
    if ((dot.x>rect.xmin)&&(dot.x<rect.xmax)&&(dot.y>rect.ymin)&&(dot.y<rect.ymax)) return 1;
    return 0;
}

 

原文地址:https://www.cnblogs.com/SueMiller/p/2136343.html