题目大意:
有个n个m维的东西,要求你把它们垒高,第i个能放在第j个上的要求是对于i,j的所有m维都有a[i][k]<a[j][k](k>=0&&k<m),问最长能有多高,并输出方案。
分析:可以转化为DAG的最长路,对于第i个能放在第j个上建一条边,那么这个问题就成了求一个有向无环图的最长路。
dp[i]表示第i个结点开始的最长路则dp[i]可以转移到dp[j](存在i->j边)
方程为:dp[i]=max(dp[j]+1)(i->j边存在) 初始为dp[i]=1;
路径方案可以通过逆向输出。

1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <vector> 5 #include <algorithm> 6 #define maxn 40 7 using namespace std; 8 int n,m; 9 int dp[maxn];//从i出发的最长路 10 vector<int>a[maxn]; 11 bool judge(int x,int y){ 12 vector<int>&la=a[x],&lb=a[y]; 13 for(int i=0;i<m;++i){ 14 if(la[i]<=lb[i])return false; 15 } 16 return true; 17 } 18 int dfs(int i){ 19 int &ans = dp[i]; 20 if(ans>0)return ans; 21 ans =1; 22 for(int j=0;j<n;++j){ 23 if(i!=j&&judge(i,j)){ 24 ans = max(ans,dfs(j)+1); 25 } 26 } 27 return ans; 28 } 29 int id; 30 void path(int u){ 31 for(int i=0;i<n;++i){ 32 if(judge(u,i)&&dp[i]==dp[u]-1){ 33 path(i);break; 34 } 35 } 36 if(u!=id)printf("%d ",u+1); 37 else printf("%d ",u+1); 38 } 39 int main (){ 40 int x; 41 while(scanf("%d%d",&n,&m)!=EOF){ 42 for(int i=0;i<n;++i){ 43 a[i].clear(); 44 for(int j=0;j<m;++j){ 45 scanf("%d",&x); 46 a[i].push_back(x); 47 } 48 sort(a[i].begin(),a[i].end()); 49 } 50 memset(dp,0,sizeof(dp)); 51 for(int i=0;i<n;++i)dfs(i); 52 int ans=0; 53 id=0; 54 for(int i=0;i<n;++i){ 55 if(ans<dp[i]){ 56 ans=dp[i]; 57 id=i; 58 } 59 } 60 printf("%d ",ans); 61 path(id); 62 } 63 }