최소 경로 덮어쓰기
Time Limit: 1000ms, Special Time Limit:2500ms, Memory Limit:32768KB
Total submit users: 19, Accepted users: 16
Problem 12499 : No special judgement
Problem description
Do you remember the box of Matryoshka dolls last week? Adam just got another box of dolls from Matryona. This time, the dolls have different shapes and sizes: some are skinny, some are fat, and some look as though they were attened. Specifically, doll i can be represented by three numbers wi, li, and hi, denoting its width, length, and height. Doll i can fit inside another doll j if and only if wi < wj , li < lj , and hi < hj . That is, the dolls cannot be rotated when fitting one inside another. Of course, each doll may contain at most one doll right inside it. Your goal is to fit dolls inside each other so that you minimize the number of outermost dolls.
Input
The input consists of multiple test cases. Each test case begins with a line with a single integer N, 1 ≤ N ≤ 500, denoting the number of Matryoshka dolls. Then follow N lines, each with three space-separated integers wi, li, and hi (1 ≤ wi; li; hi ≤ 10,000) denoting the size of the ith doll. Input is followed by a single line with N = 0, which should not be processed.
Output
For each test case, print out a single line with an integer denoting the minimum number of outermost dolls that can be obtained by optimally nesting the given dolls.
Sample Input
3
5 4 8
27 10 10
100 32 523
3
1 2 1
2 1 1
1 1 2
4
1 1 1
2 3 2
3 2 2
4 4 4
0
Sample Output
1
3
2
구도할 때 최소한의 경로로 모든 상자를 포함한다는 것을 깨달았다.
나는 탐욕스러운 방법을 사용했고 정방향과 역방향 인접표를 추가했다.
매번 욕심이 가장 많은 상자를 끼워 넣고 이 경로에 있는 상자 노드를 모두 꺼내서 상자 수++로 순환합니다.
상자가 없을 때까지.
이것은 확실히 내가 쓴 비교적 복잡한 절차이다내가 할 수 있는 물건을 다 쓸 뻔했다.아쉽게도 RE가...
#include<iostream>
#include<queue>
#include<cstdio>
using namespace std;
struct node
{
int x,y,z;
}rec[555];
struct Edge
{
int v,next;
}edge[2222];
int ptr[555],cnt[555],rptr[555];
int top[555],out[555];
int edgenum;
bool judge( node a,node b )
{
if( a.x<b.x && a.y<b.y && a.z<b.z ) return true;
if( a.y<b.x && a.x<b.y && a.z<b.z ) return true;
if( a.x<b.x && a.z<b.y && a.x<b.z ) return true;
if( a.z<b.x && a.x<b.y && a.y<b.z ) return true;
if( a.z<b.x && a.y<b.y && a.x<b.z ) return true;
if( a.y<b.x && a.z<b.y && a.x<b.z ) return true;
return false;
}
void addEdge( int u,int v )
{
edge[edgenum].v=v;
edge[edgenum].next=ptr[u];
ptr[u]=edgenum++;
edge[edgenum].v=u;
edge[edgenum].next=rptr[v];
rptr[v]=edgenum++;
}
int main()
{
int N;
while( scanf("%d",&N)!=EOF,N )
{
edgenum=0;
memset( ptr,-1,sizeof(ptr) );
memset( rptr,-1,sizeof(rptr) );
memset( out,0,sizeof(out) );
for( int i=0;i<N;i++ )
scanf( "%d %d %d",&rec[i].x,&rec[i].y,&rec[i].z );
int ans=0;
for( int i=0;i<N;i++ )
for( int j=0;j<N;j++ )
{
if( judge(rec[i],rec[j]) )
addEdge( i,j );
}
queue<int> queue;
int outnum=0;
while( outnum!=N )
{
memset( top,0,sizeof(top) );
memset( cnt,0,sizeof(cnt) );
while( !queue.empty() ) queue.pop();
for( int i=0;i<N;i++ )
{
if( out[i]==false )
{
for( int j=ptr[i];j!=-1;j=edge[j].next )
if( out[edge[j].v]==false )
top[edge[j].v]++;
}
}
for( int i=0;i<N;i++ )
if( top[i]==0&&out[i]==false )
queue.push(i);
int cur;
while( !queue.empty() )
{
cur=queue.front();
queue.pop();
for( int i=ptr[cur];i!=-1;i=edge[i].next )
{
if( out[edge[i].v]==false )
{
top[edge[i].v]--;
cnt[edge[i].v]=max( cnt[cur]+1,cnt[edge[i].v] );
if( top[edge[i].v]==0 )
queue.push(edge[i].v);
}
}
}
out[cur]=true;
outnum++;
A:
for( int i=rptr[cur];i!=-1;i=edge[i].next )
if( cnt[edge[i].v]+1==cnt[cur]&& out[edge[i].v]==false )
{
out[edge[i].v]=true;
outnum++;
cur=edge[i].v;
goto A;
}
ans++;
}
printf( "%d
",ans );
}
return 0;
}
나중에 인터넷에서 문제풀이를 찾아보니 이분도 문제였어요?
왜 그런지 도무지..인터넷에서는 최소 정점 덮어쓰기라고도 한다.
사실 오늘 이분도의 일부 개념을 다시 한 번 복습하여 최소 경로가 덮어씌워진 것이 확실하다.
그리고 최소 경로가 덮어쓰는 그림이 반드시 이분도가 아니라 Vnum-Maxmatch라는 공식으로 표현할 수 있을 뿐이다.
착실하게 2점도 공부!
다음은 AC 코드입니다.
#include<iostream>
using namespace std;
struct EDGE
{
int v,next;
}E[555555];
struct RECT
{
int x,y,z;
}rect[555];
int Edgenum,ptr[1111];
void addEdge( int u, int v )
{
E[Edgenum].v=v;
E[Edgenum].next=ptr[u];
ptr[u]=Edgenum++;
}
bool judge( RECT a,RECT b )
{
if( a.x<b.x && a.y<b.y && a.z<b.z ) return true;
return false;
}
bool vis[1111];
int match[1111];
bool Match( int cur )
{
for( int i=ptr[cur];i!=-1;i=E[i].next )
{
if( !vis[E[i].v] )
{
vis[E[i].v]=true;
if( match[E[i].v]==-1 || Match( match[E[i].v] ) )
{
match[E[i].v]=cur;
return true;
}
}
}
return false;
}
int main()
{
int N;
while( scanf("%d",&N)!=EOF,N )
{
memset( ptr,-1,sizeof(ptr) );
memset( match,-1,sizeof(match) );
Edgenum=0;
for( int i=0;i<N;i++ )
scanf( "%d %d %d",&rect[i].x,&rect[i].y,&rect[i].z );
for( int i=0;i<N;i++ )
for( int j=0;j<N;j++ )
if( judge(rect[i],rect[j]) )
{
addEdge( i,j );
//addEdge( j<<1|1,j<<1 );
}
int ans=0;
for( int i=0;i<N;i++ )
{
memset( vis,0,sizeof(vis) );
if( Match(i) )
ans++;
}
printf( "%d
",N-ans );
}
return 0;
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Ruby의 구조체 클래스은 접근자 메서드가 있는 속성 모음입니다. 클래스를 명시적으로 작성할 필요 없이. Struct 클래스는 구성원 및 해당 값 집합을 포함하는 새 하위 클래스를 생성합니다. 각 멤버에 대해 #attr_accessor 와...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.