UVa103 - Stacking Boxes

矩形嵌套,矩形之间的“可嵌套”关系是一个典型的二元关系,二元关系可以用图来建模。如果矩形X可以嵌套在Y里,我们就从X到Y连一条有向边。

这个有向图是无环的,因为一个矩形无法直接或间接地嵌套在自己内部。就是求DAG上的最长路径。

用d[i]表示从节点i出发的最长长度。最终求的答案就是d[i]中的最大值。




#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
int case_x, case_y, c, A[35][35], G[35][35], res[35], d[35];
int edg ( int i, int j ) {
    int tmp = 1;
    for ( int k = 1; k <= case_y; ++k ) {
	if ( A[i][k] >= A[j][k] ) {
	    tmp = 0;
	    break;
	}
    }
    return tmp;
}
int dp ( int i ) {     //记忆化搜索
    int &ans = d[i];             //此处较巧妙,任何对ans的读写实际上都是在对d[i]进行
    if ( ans > 0 ) return ans;
    ans = 1;
    for ( int j = 1; j <= case_x; ++j ) 
	if ( G[i][j] ) ans = max ( ans , dp( j ) + 1 );
    return ans;
}
void print ( int a ) {
    res[c++] = a;
    for ( int i = 1; i <= case_x; ++i ) {
	if ( G[a][i] && d[a] == d[i] + 1 ) { //可以确定d[a]是最长路,所以有向图的下一个点应为d[i] + 1 == d[a]
	    print ( i );
	    break;
	}
    }
}
int main ( ) {
    while ( cin >> case_x >> case_y ) {
	for ( int i = 1; i <= case_x; ++i ) {
	    for ( int j = 1; j <= case_y; ++j ) {
		cin >> A[i][j];
	    }
	    sort ( A[i] + 1, A[i] + case_y + 1 );
	}
	memset ( G, 0, sizeof ( G ) );
	for ( int i = 1; i <= case_x; ++i )  //此处是建图的过程
	    for ( int j = 1; j <= case_x; ++j ) {
		if ( edg ( i, j ) ) G[i][j] = 1;
	    }
	memset ( d, 0, sizeof ( d ) );
	for ( int i = 1; i <= case_x; ++i ) 
	    dp ( i );
	int MAX = -1, pos = -1;
	for ( int i = 1; i <= case_x; ++i ) 
	    if ( d[i] > MAX ) {
		MAX = d[i];
		pos = i;
	    }
	cout << MAX << endl;
	c = 0;
	print ( pos );
	for ( int i = 0; i < c - 1; ++i ) 
	    cout << res[i] << " ";
	cout << res[c - 1] << endl;
    }
}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值