链接:http://acm.hdu.edu.cn/showproblem.php?pid=1160
题意:很多老鼠,每个老鼠有w(重量)和s(速度)两个属性,要求选一些老鼠,使他们的w严格递增且s严格递减,输出个数和老鼠的标号
思路:按照w升序排序,再求s的最长上升子序列(LIS),不过要注意的是本题还要求记录路径,为了方便,我用的是O(n^2)的路径存储算法我不会nlogn的,这里贴出nlogn别人的算法←点这里。pre[i]是记录该节点的前面是谁,更新dp[i]的时候顺手更新pre[i]就好啦,不过跑完一个dp[i]后记得更新所有dp[i]中最大的那个,也就是max_dp
代码:
1 #include<bits/stdc++.h> 2 #define inf 0x3f3f3f3f 3 using namespace std; 4 5 typedef long long ll; 6 typedef long double ld; 7 8 const int M = int(1e5)*2 + 5; 9 const int mod = 10056; 10 11 inline int lowbit(int x) { 12 return x & (-x); 13 } 14 15 struct node{ 16 int w,s,ind; 17 }; 18 node a[M]; 19 bool cmp(node a,node b){ 20 return a.s==b.s?a.w<b.s:a.s>b.s; 21 } 22 23 int dp[M]; 24 int pre[M]; 25 int main(){ 26 int k=0; 27 while(~scanf("%d%d",&a[k].w,&a[k].s)){ 28 a[k].ind=k; 29 dp[k]=1; 30 pre[k]=-1; 31 k++; 32 } 33 34 sort(a,a+k,cmp); 35 // for(int x=0;x<=k;x++) cout<<a[x].w<<" "<<a[x].s<<endl; 36 37 int max_dp=0,max_i; 38 for(int i=0;i<k;i++){ 39 for(int j=0;j<i;j++){ 40 if(a[j].w<a[i].w && a[j].s>a[i].s){ 41 if(dp[i]<dp[j]+1){ 42 dp[i]=dp[j]+1; 43 pre[i]=j; 44 } 45 } 46 } 47 if(max_dp<dp[i]){ 48 max_dp=dp[i]; 49 max_i=i; 50 } 51 } 52 53 cout<<max_dp<<endl; 54 55 stack<int> st; 56 st.push(a[max_i].ind); 57 max_i=pre[max_i]; 58 while(max_i!=-1){ 59 st.push(a[max_i].ind); 60 max_i=pre[max_i]; 61 } 62 63 while(!st.empty()){ 64 cout<<st.top()+1<<endl; 65 st.pop(); 66 } 67 return 0; 68 }
备注:是不是很简单