题型:DP
题意:
有许多只老鼠,每只体重w,速度s。现在给这些老鼠排队,使得体重严格递增,速度严格递减,求最长数目和队伍里的老鼠的id。
分析:
首先进行二级排序,按w递增排,如果w相同的,按s递减排。
然后进行dp,类似于最长递增子序列的思想,假设当前状态是i老鼠,转移的时候,如果j老鼠的w小且s大,那么就继承那个状态(j<i)。
状态转移方程为:dp[i] = max{dp[i],dp[j]+1]}
因为需要输出所选用的老鼠,所以需要开一个数组记录一下路径,输出的时候逆序输出路径。
代码:
#include<iostream>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<stack>
#define mt(a,b) memset(a,b,sizeof(a))
using namespace std;
const int M = 1024;
struct Node{
int w;
int s;
int id;
}mice[M];
int dp[M],re[M];
bool cmp(Node A,Node B){
if(A.w == B.w) return A.s > B.s;
return A.w < B.w;
}
int main(){
// freopen("in.txt","r",stdin);
int pre = 0;
while(~scanf("%d%d",&mice[pre].w,&mice[pre].s)){
mice[pre].id = pre+1;
pre++;
}
sort(mice,mice+pre,cmp);
for(int i=0;i<pre;i++){
dp[i] = 1;
}
mt(re,-1);
for(int i=0;i<pre;i++){
for(int j=0;j<i;j++){
if(mice[i].w>mice[j].w && mice[i].s<mice[j].s && dp[i]<dp[j]+1){
dp[i] = dp[j] + 1;
re[i] = j;
}
}
}
//
// for(int i=0;i<pre;i++){
// printf("%d ",dp[i]);
// }
// puts("");
// for(int i=0;i<pre;i++){
// printf("%d ",re[i]);
// }
// puts("");
int maxn = 1;
int pos = 0;
for(int i=0;i<pre;i++){
if(maxn < dp[i]){
maxn = dp[i];
pos = i;
}
}
printf("%d\n",maxn);
stack<int> st;
st.push(mice[pos].id);
while(~re[pos]){
pos = re[pos];
st.push(mice[pos].id);
}
while(!st.empty()){
printf("%d\n",st.top());
st.pop();
}
return 0;
}