DP(001)-洛谷P1233木棍加工

一、算法分析

代码里面讲的已经比较详细了,这道题涉及LIS类的问题,而且涉及到dilworth定理。

二、代码及注释

#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;
int n;
struct stk{
	int l;
	int w;
	stk(int lp,int wp):l(lp),w(wp){}
};
bool cmp(stk x,stk y){
	return x.l>y.l;
}
vector<stk> a;
vector<int> b,c;
int main(){
	
	freopen("in.txt","r",stdin);
	freopen("out.txt","w",stdout);
	
	cin>>n;
	int lp,wp;
	for(int i=0;i<n;i++){
		cin>>lp>>wp;
		a.push_back(stk(lp,wp));
	}
	sort(a.begin(),a.end(),cmp);                       //处理这种嵌套矩形类问题,因为有两个参数,通常我们确定其中一个,然后处理另外一个。此处就是先把长度排好序,再处理宽度的最长不上升子序列 
	for(int i=0;i<n;i++){                              //这样的问题显然就要对木棍的宽度进行遍历 
		b.push_back(a[i].w);                             //c的最后一个元素是我们假设的不下降子序列的结束点(会持续更新),不上升子序列的最小划分等于最长上升子序列的长度,所以这里求的是最长上升的子序列长度 	
	}
	c.push_back(b[0]); 
  for(int i=0;i<n;i++){                               //接下来就是一个最长上升子序列的模板了 
    if(b[i]>c.back()) c.push_back(b[i]);             //如果有比结束点大的,就加进序列里面 
//否则就通过二分查找,更正前面的序列 
    else{
		  int l=0,r=c.size()-1;
		while(l<r){
			int mid=(l+r)/2;
			if(c[mid]>=b[i]){                              //这样的二分查找,不一定会找到一个准确的值等于b[i],但是会找到一个尽量接近b[i]的值 
				r=mid;
			}
			else{
				l=mid+1;
			}
		}
		//cout<<"??"<<c[l]<<' '<<b[i]<<endl;             //这里可以输出一下中间变量作为测试 
		c[l]=b[i];  
    }
	} 
	cout<<c.size();
	return 0;
} 

注明:解题思路参考了洛谷该题的题解的第一篇即用户名为dreagonm写的题解,参考了其中部分思想,在此注明并表示感谢。
参考文献

发布了50 篇原创文章 · 获赞 7 · 访问量 1139

猜你喜欢

转载自blog.csdn.net/numb_ac/article/details/103396897