1、又是一道DP,一次AC,发现DP题只要你会做就不会错。。。这点比那些用BT数据坑人的模拟题好多了。
2、本题可以转化为DAG上任意起点的最长路问题,易错的地方主要有:k和n容易搞混,k是盒子数而n是盒子维数,这让习惯以n来计数的我很不适应;最佳答案要单独用path数组保存,否则会被覆盖;注意交题的时候把freopen给注释掉。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int a[40][15],G[40][40],d[40],path[40];
int k,n,maxn,maxi;
bool is_smaller(int *a,int *b){
for(int i=0;i<n;i++)
if(a[i]>=b[i]) return false;
return true;
}
void init(){
memset(a,0,sizeof(a));
memset(G,0,sizeof(G));
memset(d,0,sizeof(d));
for(int i=0;i<k;i++)
for(int j=0;j<n;j++)
scanf("%d",&a[i][j]);
for(int i=0;i<k;i++)
sort(a[i],a[i]+n);
for(int i=0;i<k;i++)
for(int j=0;j<k;j++)
if(i!=j&&is_smaller(a[i],a[j]))
G[i][j]=1;
}
int dp(int i){
int &ans=d[i];
if(ans>0)return ans;
ans=1;
for(int j=0;j<k;j++)
if(G[i][j]) ans=max(ans,dp(j)+1);
return ans;
}
void print_ans(int i){
printf("%d ",i+1);
for(int j=0;j<k;j++) if(G[i][j]&&path[i]==path[j]+1){
print_ans(j);
break;
}
}
int main(){
//freopen("a.txt","r",stdin);
while(scanf("%d%d",&k,&n)==2){
init();
maxn=0;maxi=0;
memset(path,0,sizeof(path));
for(int i=0;i<k;i++){
memset(d,0,sizeof(d));
dp(i);
if(d[i]>maxn){
maxn=d[i];
maxi=i;
memcpy(path,d,sizeof(path));
}
}
printf("%d\n",maxn);
print_ans(maxi);
printf("\n");
}
return 0;
}