您的位置:首页 > 其它

UVA103DAG上最长路径+字典序输出

2013-11-27 23:17 501 查看
题目描述:

给定n维的m个物品,按照各维长度严格递增的排序,求最长的序列,并按照字典序输出。

例如n=4,(1 2 3 4)之后是(2,3,4,5)就可以。

思维过程:

《入门经典》上DAG模型。

枚举状态结点时,出现了思维误区。想要把n维的n个长度滚动成n种状态点。

上述考虑固然可以,但是不是n种状态点,因为是按顺序排列,所以是n!种,然而n《=30。

后来想到了贪心的优化,我们的重点是一个能嵌套到另一个种,所以我们将变长从大到小排序。

例如:a1<=a2<=a3<=a4<=a5

b1<=b2<=b3<=b4<=b5

假设把b3换到b2之前,如果b2>a3,那么固然b3>a2,所以排序后比较能保证能放就一定能放进

算法分析:

1、每个状态抽象成一个点,既求有向无环图上求最长路径

2、没有终点,故枚举每个终点,结束点是每一个状态自成单点,既d[i]=0;

3、为输出字典序,故枚举的是dp(i)以i为终点。

4、调试的时候可以输出所有dp,方便模拟状态转移

#include<iostream>
#include<string.h>
#include<algorithm>
#include<stdio.h>
#define maxn 310//最多的状态数
using namespace std;
int d[maxn];
int G[maxn][maxn];
int m,n;
struct Node{
int a[15];//各个维度的长度
}node[maxn];
void print_path(int p){
if (d[p]>1) printf("%d ",p);else printf("%d\n",p);
for(int i=1;i<=m;i++)
if (d[i]+1==d[p] && G[p][i]==1) {print_path(i);break;}
}
void readin(){
for(int i=1;i<=m;i++){
for(int j=1;j<=n;j++)
scanf("%d",&node[i].a[j]);
sort(node[i].a+1,node[i].a+n+1);
}
}
void builtG(){
memset(G,0,sizeof(G));
for(int i=1;i<=m;i++){
for(int j=1;j<=m;j++){
if (i==j) continue;
int mark=1;
for(int k=1;k<=n;k++)
if (node[i].a[k]>=node[j].a[k]){mark=0;break;}
if (mark) G[i][j]=1;
}
}
}
int dp(int i){
int &ans=d[i];
if (ans>0) return ans;
ans=1;
for(int j=1;j<=m;j++) if (G[i][j]) ans=max(ans,dp(j)+1);
return ans;
}
void slove(){
readin();
builtG();
memset(d,0,sizeof(d));
int ans=-1;int p=-1;
for(int i=1;i<=m;i++){
int k=dp(i);
if (ans<k) {ans=k;p=i;}
}
printf("%d\n",ans);
print_path(p);
return ;
}
int main(){
while(~scanf("%d%d",&m,&n)) slove();
return 0;
}


  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: