acm动态规划之最长路问题UVA103stocking boxes做题报告


 

UVA103Stacking Boxes

在这个问题中,你要分析一组n维盒子的某个性质。你要确定出盒子的最长嵌套串,也就是说一系列的盒子b1、b2、……、bk,一个套一个,使所有的bi都嵌套在bi+1内。

对于一个盒子D = (d1, d2, ..., dn)和另一个盒子E = (e1, e2, ..., en),如果存在一种di的排列,使重排的每个维度的值都小于盒子E中对应维度的值,则盒子D可嵌入盒子E。这个过程和旋转盒子D,看它是否能套入E的过程类似。然而,若需满足所有维度的排列,盒子D必须是可以扭曲的,而不仅仅是旋转。

定义嵌套关系如下:盒子D = (d1, d2, ..., dn)和E = (e1, e2, ..., en),当存在一种1...n的排列p使得(dp(1), dp(2), ..., dp(n))能够匹配(e1, e2, ..., en),即对所有的1 ≤ i ≤ n都有dp(i) < ei,那么就认为D可以嵌入E。

输入由一组的盒子序列构成。每个盒子序列的开始是盒子的总数k和维度n(出现在同一行)。

第一行下面有k行,每行用n个(n由第一行确定)数表示一个盒子,这n个数由一个或多个空格隔开。序列中的第i行(1 ≤ i ≤ k)表示第i个盒子。

输入的数据中可能存在多个盒子序列。你的程序应该处理全部数据,针对每个序列,找出k个盒子中的哪几个可以构成最长的嵌套串,以及这个嵌套串的长度(嵌套串中盒子的数量)。

在这个问题中最大的维度是10,最小的维度是1。最大的盒子序列长度为30。

 输出

 对应输入的每个盒子序列,应在第一行输出最长的嵌套串长度,在下一行按顺序输入组成这个嵌套串的盒子列表。嵌套串中最“小”的或着说是最“内”的盒子应该放在第一位,之外的一个(如果存在)放在第二位,以此类推。

盒子的编号要按它们在输入数据中的位置相对应。(输入的第一个盒子为1号,第二个盒子为2号,等等)

 如果存在多于一个嵌套串的长度同为最长,可输出其中的任何一个。

题目分析:

盒子嵌套关系是一个典型的有向无环图模型 这个要先建立这个图然后再来找最长路;这样时间复杂度会降低; 建图的时间复杂度o(n^3)太大了 看一看有没有别的办法;

然后找最大串,就是遍历所有向他入的结点,找到最大的加一,这样时间复杂度是o(n^2); 在这个过程中同时用数组记下最长路;用空间来换时间; 只需要开一个数组存储每一个结点的上一个结点, 然后输出的时候用递归从头输出, 这时候时间复杂度从o(n^2)到o(n)

代码如下

  1 /*
  2 盒子嵌套关系是一个典型的有向无环图模型
  3 这个要先建立这个图然后再来找最长路;这样时间复杂度会降低;
  4 建图的时间复杂度o(n^3)太大了 看一看有没有别的办法; 
  5 
  6 然后找最大串,就是遍历所有向他入的结点,找到最大的加一,这样时间复杂度是o(n^2);
  7 在这个过程中同时用数组记下最长路;用空间来换时间; 只需要开一个数组存储每一个结点的上一个结点,
  8 然后输出的时候用递归从头输出, 这时候时间复杂度从o(n^2)到o(n) 
  9 */
 10 //
 11 #include <set>
 12 #include <map>
 13 #include <cmath>
 14 #include <queue>
 15 #include <stack>
 16 #include <string>
 17 #include <vector>
 18 #include <cstdio>
 19 #include <cstring>
 20 #include <iostream>
 21 #include <algorithm>
 22 
 23 using namespace std;
 24 typedef long long ll;
 25 typedef unsigned long long ull;
 26 
 27 #define debug puts("here")
 28 #define rep(i,n) for(int i=0;i<n;i++)
 29 #define rep1(i,n) for(int i=1;i<=n;i++)
 30 #define REP(i,a,b) for(int i=a;i<=b;i++)
 31 #define foreach(i,vec) for(unsigned i=0;i<vec.size();i++)
 32 #define pb push_back
 33 #define RD(n) scanf("%d",&n)
 34 #define RD2(x,y) scanf("%d%d",&x,&y)
 35 #define RD3(x,y,z) scanf("%d%d%d",&x,&y,&z)
 36 #define RD4(x,y,z,w) scanf("%d%d%d%d",&x,&y,&z,&w)
 37 #define zero(x,y) memset(x,0,y)
 38 #define nega_1(x,y) memset(x,-1,y)
 39 
 40 const int MAX=50;
 41 int G[MAX][MAX];//记录有向图信息;0表示没有关系,1表示i把j嵌套之,-1表示没有访问 
 42 int box[MAX][MAX];// 保存图的信息; 
 43 int longest[MAX];//记录每个结点的前一个最长结点;
 44 int leng_th[MAX];//记录每个结点的最长长度; 
 45 int vis[MAX];//记录有没有访问过; 
 46 int n,k;
 47 int long_path(int i)
 48 {
 49     int j;
 50     if(vis[i])return leng_th[i];
 51     vis[i]=1;
 52     rep(j,n)
 53     {
 54         if(G[i][j]==1&&leng_th[i]<=long_path(j)+1)
 55         {
 56             leng_th[i]=long_path(j)+1;
 57             longest[i]=j;        
 58         }
 59     }
 60     return leng_th[i];
 61 }
 62 void print_path(int i)
 63 {
 64     //递归终点是找到-1;
 65     if(i==-1)return;
 66     print_path(longest[i]);
 67     cout<<i+1<<" "; 
 68 }
 69 int main()
 70 {
 71     #ifndef ONLINE_JUDGE
 72     freopen("F://code//txt//24.txt","r",stdin);
 73     #endif
 74     //int n,k;//n表示行数,k表示箱子纬度个数;
 75     int i,j,m,w;
 76     while(cin>>n>>k)
 77     {
 78         rep(i,n)
 79         {
 80             rep(j,k)
 81             {
 82                 cin>>box[i][j];
 83             }
 84         }//读完了所有的图信息;
 85         //开始构造图,用邻接矩阵;
 86         nega_1(G,sizeof G);
 87         rep(i,n)
 88             sort(box[i],box[i]+k);
 89         rep(i,n)
 90         {
 91             rep(j,n)
 92             {
 93                 if(i==j)
 94                 {
 95                     G[i][j]=0;
 96                     continue;
 97                 }
 98                 if(G[i][j]==-1)
 99                 {
100                     int success=1;
101                     rep(m,k)
102                     if(box[i][m]<=box[j][m])
103                     {
104                         success=0;
105                         break;
106                     }
107                     if(success)
108                     {
109                         G[i][j]=1;
110                         G[j][i]=0;
111                     
112                     }
113                     else
114                         G[i][j]=0;
115                 } 
116             }
117         }//图建立完成 
118         //使用递归进行;找最长路; 
119         zero(vis,sizeof vis);
120         nega_1(longest,sizeof longest);//为了防止0的重复; 
121         zero(leng_th,sizeof leng_th);
122         
123         rep(i,n)
124         {
125             long_path(i);
126         }//求最长路;
127         int longest_len=0;
128         int end_point;
129         rep(i,n)
130          if(longest_len<leng_th[i])
131          {
132              longest_len=leng_th[i];
133              end_point=i;
134           } 
135          cout<< longest_len+1<<endl;
136          print_path(end_point);
137          cout<<endl;
138         
139     } 
140     return 0;
141 } 
原文地址:https://www.cnblogs.com/dragonfive/p/2990575.html