UVa 103.Stacking Boxes

dp,盒子嵌套问题。

用edge【i】【j】二维数组来记录盒子i 能够嵌套到盒子j 中。

在判断能否嵌套时,先将每个盒子的各个数据按从小到大排序,然后再逐项进行比较,如果每个数据都较小,则该盒子可被后者嵌套。

用dp【i】表示从盒子i开始的最长盒子串。

最后打印出最长盒子串时打出字典序最小的即可。

 

#include <iostream>
#include <cmath>
#include <cstdio>
#include <string.h>
#include <algorithm>
using namespace std;

int k,n;
bool first;
int edge[31][31], box[31][11], dp[31];
bool small(int a, int b)        //判断盒子a是否比盒子b小
{
	int i;
	for( i=0; i<n; i++)
		if( box[a][i] >=box[b][i])
			return 0;
	return 1;
}
int f( int i)           //记忆化搜索
{
	int& ans =dp[i];
	if( ans> 0) return ans;
	ans =1;
	int j;
	for( j=1; j<=k; j++)
		if( edge[i][j] )
			ans =max(ans, f(j)+1);
	return ans;
}
void outpath( int i)   //打印出路径,输出字典序最小的路径
{
	if( !first)
		printf(" ");
	else
		first =0;
	printf("%d", i);
	int j;
	for( j=1; j<=k; j++)
		if( edge[i][j] && dp[i] ==dp[j]+1)
		{
			outpath( j);
			break;
		}
}

int main()
{
	while( scanf("%d%d", &k, &n)!=EOF )
	{
		int i,j;
		for( i=1; i<=k; i++)
		{
			for( j=0; j<n; j++)
				scanf("%d",&box[i][j] );
			sort(box[i], box[i]+n);
		}
		memset( edge, 0,sizeof(edge));
		memset( dp, 0,sizeof(dp) );
		for( i=1; i<=k; i++)         //找出所有盒子之间的边
			for( j=1; j<=k; j++)
				if( small( i,j))
					edge[i][j] =1;
		int c=0, flag=0;
		for( i=1; i<=k; i++)
			if( f(i)>c )
			{
				c  =f(i);
				flag =i;
			}
		printf("%d\n",c);
		first=1;
		outpath( flag);
		printf("\n");
	}
	return 0;
}


 

你可能感兴趣的:(UVa 103.Stacking Boxes)