UVA 103

  题目让求给定的n个d维物体中可以嵌套的最长序列的长度和序列,显然需要先将每个物体的d个参数排序,此时可以用类似字典序的方法给出任何两个物体的大小关系,这里需要注意的是,任何两个物体对应位置上的参数若相等则不算包含,故抽象为DAG求最长路径。这里有两种状态的定义方法,第一种:定义状态dp(i)为以第i个物体为最外层最多可以嵌套物体的数量,那么状态转移方程为:dp(i)=Max{dp(j)}+1,其中i必须可以包含j;第二种:定义状态dp(i)为以物体i为基础,外层最多能包裹的物体数量,状态转移方程同为dp(i)=Max{dp(j)}+1,但其中i必须可以被j包含。

  无意中发现,虽然两种方法的有向图对应边方向相反,但所构造的DAG邻接矩阵m[0][i](1<=i<=n)均为true,原因在于无论怎么搜索,必然要设置边界条件,而0在第一种方法中表示能被任何物体包裹,在第二种方法中表示能包含任何物体。最后,两种方法还有一点不同是输出时,第一种需要倒转路径,而第二种直接输出即可。

  下面给出第二种方法的代码:

#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
int s[35][15];
bool m[35][35];
int total[35],path[35],n,d;
int dp(int pos)
{
	if(total[pos]!=-1) return total[pos];
	int Max=-1,Maxp=0;
	for(int i=0;i<=n;i++) if(m[i][pos]){// 如果i可以包裹住pos
		int t=dp(i);
		if(t>Max){
			Max=t;
			Maxp=i;
		}
	}
	path[pos]=Maxp;//记录路径
	total[pos]=Max+1;
	return total[pos];
}
int main()
{
	while(cin>>n>>d){
		memset(m,false,sizeof(m));
		memset(total,-1,sizeof(total));
		total[0]=0;path[0]=0;
		for(int i=1;i<=n;i++){
			for(int j=0;j<d;j++) cin>>s[i][j];
			sort(s[i],s[i]+d);
			m[0][i]=true;//假设0是无限大的,可以包裹任何物体
		}
		for(int i=1;i<=n;i++)
			for(int j=1;j<=n;j++){
				bool yes=true;
				for(int k=0;k<d;k++) if(s[i][k]<=s[j][k]){
					yes=false;break;
				}//判断i是否可以包裹j
				if(yes) m[i][j]=true;
			}
		int Max=-1,Maxp;
		for(int i=1;i<=n;i++){
			int t=dp(i);
			if(t>Max){
				Max=t;Maxp=i;
			}
		}
		cout<<Max<<endl;
		while(Maxp){
			cout<<Maxp;
			Maxp=path[Maxp];
			if(Maxp) cout<<" ";
			else cout<<endl;
		}
	}
	return 0;
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值