问题描述:
发神给我出的一个题
给出一个数n
输入n个 1-n 的数,不能重复,
求使上述输出的数转换为正序排列的数的最小泳道数
条件:
可以利用多个泳道(也就是队列),每个泳道可以装若干个数
//思路 每个数前面的数只能是比次数小的,不能是比次数大的,如果当前不存在一个泳道的最后一个数小于要加如的数,则size++,
//如果存在多个符合条件的,则插入到当前泳道中队尾最大的数后面,因为肯定是越小的越先排出泳道,如果放到较小的后面,较小的先输出了,
//此后再来一个数,如果这个数较小,就可以直接插入空的队列,然后输出
代码如下
#include<queue>
#include<cstdio>
#include<iostream>
#include<deque>
#include<cstring>
using namespace std;
int Max,n,x;
int y;
int x1;
int dir;
int in[100001];
queue<int>que;
priority_queue<int, vector<int>, greater<int> > gre;
deque<int>change[100001];
bool Find()
{
dir=1;
int judge=0;
for(int i=1; i<=Max; ++i)
{
if(change[i].size()&&change[i].back()<y)
{
dir=i;
break;
}
}
for(int i=1; i<=Max; ++i)
{
if(change[i].size()&&change[i].back()<y&&change[i].back()>=change[dir].back())
{
dir=i;
judge=1;
}
}
return judge;
}
void Insert()
{
if(Find())
{
change[dir].push_back(y);//放到合适的位置
}
else
{
++Max;
change[Max].push_back(y);
}
in[y]=0;
}
void slove()
{
while(!gre.empty())
{
x=gre.top();
if(!in[x])
;
else
{
while(que.size()&&que.front()!=x)
{
y=que.front();
que.pop();
Insert();
}
y=x;
Insert();
que.pop();
}
gre.pop();
}
}
int main()
{
while(cin>>n)
{
if(!n)
cout<<0<<endl;
else
{
memset(in,1,sizeof(in));
for(int i=1; i<=n; ++i)
{
cin>>x;
que.push(x);
gre.push(x);
}
Max=0;
slove();
cout<<Max<<endl;
}
}
}
上面的应该是模拟的思路,也可以说是用了贪心的思想
接下来这一种办法将问题转换
我们可以分析出(直接或者你看了上面的模拟过程)其实本题要求的就是输入的数可以分为多少个不含逆序数对的组
举个例子
n=7
依次输入 1 6 2 4 5 7 3
然后我们就可以把上面的数分成
1 6 7 2 4 5 3 这三组
然后结果就是3
用代码如何实现呢,我写的代码如下,还是用贪心的思想,如果你有动态规划的算法,请在评论区贴出你的代码或者说出你的思路。
#include<cstdio>
#include<iostream>
#include<vector>
using namespace std;
int n,Max;
vector<int> v;
void slove()
{
int x;
for(int i=1;i<=n;++i)
{
cin>>x;
v.push_back(x);
}
int f,it,dir;
while(!v.empty())
{
f=v[0];
dir=0;
it=1;
for(;it<v.size();++it)
{
if(v[it]>f)
{
dir=it,f=v[it];
v.erase(v.begin()+dir);
--it;
}
}
v.erase(v.begin());
Max++;
}
}
int main()
{
while(cin>>n)
{
Max=0;
if(!n)
;
else
{
slove();
}
cout<<Max<<endl;
}
}