给了n个(n<=5000)木棍的长度hi与宽度wi(均小于10000),现在机器要打磨这些木棍,如果相邻连个木棍hi<=hj并且wi<=wj就不需要调整机器,问如何排序使得机器调整的次数最少。
【LIS】基本上和【这题】相同,但是那题中,如果hi=hj并且wi=wj长度会增加,而这道题则相反。
还是类似于那一题的思路:
假设wi>wj,如果hi>=hj,显然符合条件,答案不需要增加。
还是wi>wj,如果hi<hj,那么答案+1
假设wi=wj,如果hi>=hj,那么答案也是不需要增加。
由于要使机器调整次数尽量小,因此把w降序排列,当wi=wj时,让hi>=hj(h降序排列),然后对h求最长严格上升子序列即可。
#include<cstdio> #include<cstring> #include<cmath> #include<iostream> #include<algorithm> #include<set> #include<map> #include<stack> #include<vector> #include<queue> #include<string> #include<sstream> #define eps 1e-9 #define ALL(x) x.begin(),x.end() #define INS(x) inserter(x,x.begin()) #define FOR(i,j,k) for(int i=j;i<=k;i++) #define MAXN 5005 #define MAXM 40005 #define INF 0x3fffffff using namespace std; typedef long long LL; int i,j,k,n,m,x,y,T,ans,big,cas,num,len; bool flag; struct node { int s,b,i; }p[MAXN]; int dp[MAXN]; bool cmp(node x,node y) { if (x.s==y.s) return x.b>y.b; return x.s>y.s; } int main() { scanf("%d",&T); while (T--) { scanf("%d",&n); for (i=1;i<=n;i++) { scanf("%d%d",&p[i].s,&p[i].b); p[i].i=i; } sort(p+1,p+1+n,cmp); num=0; for (i=1;i<=n;i++)//求最长上升子序列 { if (p[i].b>dp[num]) { dp[++num]=p[i].b; }else { k=lower_bound(dp+1,dp+1+num,p[i].b)-dp; dp[k]=p[i].b; } } printf("%d\n",num); } return 0; }
时间: 2024-10-11 04:10:23