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 } 

 

你可能感兴趣的:(动态规划)