轮船问题
原题链接
描述
某国家被一条河划分为南北两部分,在南岸和北岸总共有
输入
包括了若干组数据,每组数据格式如下:
第一行两个由空格分隔的整数
第二行是一个整数
输出
输出每一组数据在安全条件下能够开通的最大航线数目。
输入样例 1
30 4
5
4 5
2 4
5 2
1 3
3 1
输出样例 1
3
动态规划
这道题求选出最大的航线数目,结合题意,很明显就是动态规划嘛。
首先要知道,如何判断两条航线交叉与否,不难发现有两种情况:
(假设a[i]是这边,b[i]就是另一边)
-
a[i]>b[i]
-
a[i]<b[i]
当a[i]>b[i]时,如果a[j]<a[i] && b[j]>b[i] 就是重叠。
当a[i]<b[i]时,如果a[j]>a[i] && b[j]<a[i] 就是重叠。
一看,只要保证其中a的顺序,那不就是求b的最长上升子序列吗?
直接排序,然后求最长上升子序列。
代码
#include<bits/stdc++.h>
using namespace std;
struct Node {
int l,r;
}a[11111];
bool cmp(Node x ,Node y) {
return x.l<y.l;
}
int dp[1111111];
int x,y,n;
int main() {
cin>>x>>y>>n;
for(int i=1;i<=n;i++) {
cin>>a[i].l>>a[i].r;
dp[i]=1;
}
sort(a+1,a+n+1,cmp);
int ans=0;
for(int i=1;i<=n;i++) {
for(int j=1;j<i;j++) {
if(a[i].r>a[j].r)
dp[i]=max(dp[i],dp[j]+1);
}
}
for(int i=1;i<=n;i++) {
ans=max(ans,dp[i]);
}
cout<<ans;
return 0;
}
其他
其实还有一种方法,就是用数组a的值表示y的位置,用下标表示x的位置。
遍历1~x,对a数组求最长上升子序列,类似于桶排序吧。
热心同学的代码
#include<bits/stdc++.h>
using namespace std;
int f[60100],x,y,n,p;
int dp[60100],ans;
int main(){
memset(f,-1,sizeof(f));
cin>>x>>y>>n;
for(int i=1;i<=n;++i){
cin>>p;
cin>>f[p];
}
for(int i=1;i<=x;i++)dp[i]=1;
for(int i=1;i<=x;i++){
if(f[i]!=-1){
for(int j=1;j<i;j++){
if(f[i]>f[j])dp[f[i]]=max(dp[f[i]],dp[f[j]]+1);
}
ans=max(dp[f[i]],ans);
}
}
cout<<ans;
return 0;
}
时间复杂度
在时间复杂度上,最优情况下第二种方法≈第一种方法=
最坏情况下,第二种方法是
本文作者:cjrqwq
本文链接:https://www.cnblogs.com/yfzqwq/p/18492852
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步