JLU数据结构荣誉课——第七次上机实验
7-1 序列调度 (100 分)
题目分析
模拟法:使用一个栈,在读入输出序列时,若读入的数不是顺序序列对应的数,那顺序序列中的该数应该入栈,若读入的数小于先顺序序列中指向的数,所需的数应在栈中寻找,若在栈顶则可以取得,否则不可取。
代码实现
#include <bits/stdc++.h>
using namespace std;
stack<int>stk;
int main()
{
int n,m,l=0;
cin>>n;
cin>>m;
for(int i=0;i<m;i++)
{
int t,k,zzz=1,lll=0;
cin>>t;
if(i!=0)printf("\n");
while(!stk.empty())stk.pop();
for(int j=0;j<t;j++)
{
int pd=1;//判断标志
cin>>k;
if(!stk.empty())
{
int yyy=stk.top();
if(yyy==k)
{
stk.pop();
pd=0;
}
}
if(pd)
{
if(k==zzz)
{
zzz++;
}
else
while(k!=zzz)
{
stk.push(zzz++);
if(stk.size()>=n)
{
lll=2;
}
}
}
if(lll==2)
{
printf("No");
lll++;
}
else if(j==t-1&&lll==0)printf("Yes");
}
}
}
7-2 最大最小差 (100 分)
题目分析
维护两个单调队列,取最大值和最小值,取最大的两个值和最小的两个值依次操作,所得到的便是最大(最小)值。
代码实现
#include<stdio.h>
#include<malloc.h>
#include <bits/stdc++.h>
using namespace std;
struct Node1
{
long long int value;
bool operator<(const Node1& a)const
{
return value< a.value;
}
};
struct Node2
{
long long int value;
bool operator<(const Node2& a)const
{
return value> a.value;
}
};
priority_queue<Node1> q1;//最大值
priority_queue<Node2> q2;//最小值
int main()
{
int n,t;
scanf("%d",&n);
for(int i=0;i<n;i++)
{
scanf("%d",&t);
Node1 t1;
Node2 t2;
t1.value=t;
t2.value=t;
q1.push(t1);
q2.push(t2);
}
// if(n==1)printf("%d\n%d",)
for(int i=0;i<n-1;i++)
{
Node1 t1,t2,zz1;
Node2 t3,t4,zz2;
t1=q1.top();
q1.pop();
t2=q1.top();
q1.pop();
zz1.value=(t1.value*t2.value)+1;
q1.push(zz1);
t3=q2.top();
q2.pop();
t4=q2.top();
q2.pop();
zz2.value=(t3.value*t4.value)+1;
q2.push(zz2);
}
long long int answer;
Node1 t1;
Node2 t2;
t1=q1.top();
t2=q2.top();
answer=t2.value-t1.value;
cout<<answer;
}
7-3 二叉树最短路径长度 (100 分)
题目分析
根据中跟序列和先跟序列找根,先在先跟序列中找节点,在中跟序列中位于其左边的是他的左子树内容,右边的是其右子树内容。
代码实现
#include<bits/stdc++.h>
using namespace std;
#define MAX_ 20005
queue<int> que;
int a[MAX_],b[MAX_];
int left_[MAX_],right_[MAX_],v[MAX_];
int n;
int Creat(int a[],int b[],int n){
int tem_0=a[0],zzz;
if(n==0)return 0;
for(zzz=0;zzz<n;zzz++){
if(b[zzz]==tem_0)
break;
}
left_[tem_0]=Creat(a+1,b,zzz);
right_[tem_0]=Creat(a+zzz+1,b+zzz+1,n-zzz-1);
return tem_0;
}
int main(){
cin>>n;
que.push(1);
for(int j=1;j<=n;j++){
cin>>a[j];
}
for(int j=1;j<=n;j++){
cin>>b[j];
}
Creat(a+1,b+1,n);
for(int j=1;j<=n;j++){
cin>>v[j];
}
while(!que.empty()){
int omm=que.front();
que.pop();
if(left_[omm]){v[left_[omm]]+=v[omm];que.push(left_[omm]);}
if(right_[omm]){v[right_[omm]]+=v[omm];que.push(right_[omm]);}
}
for(int b=1;b<n;b++){
cout<<v[b]<<" ";
}
cout<<v[n]<<endl;
return 0;
}
7-4 方案计数 (100 分)
题目分析
拓扑排序,找关键路径,并求关键路径的长度以及条数。
需要注意的是,关键路径的条数最多能达到100位,需要用到大整数加法,乘法。
这道题当时不太会,后来借鉴了大佬的方法,,
代码如下
#include<bits/stdc++.h>
using namespace std;
const int Max=10010;
int num[Max];
int zz[Max];
int a[Max];
queue<int>que;
vector<int>map_[Max];
struct Node {
int ll;
int rode[102];
Node(int zzz=0){
ll=zzz;
memset(rode, 0, sizeof(rode));
}
void operator =(const Node& p) {
for (int j = 0;j < 102;j++)
rode[j] = p.rode[j];
ll = p.ll;
}
void operator +=(const Node& p) {
int j, long_0,k=0,l,l0;
long_0 = p.ll;
if (ll < long_0) { l = ll; l0 = long_0; }
else { l = long_0; l0 = ll; }
for (j = 0;j < l;j++) {
k = rode[j] + p.rode[j] + k;
rode[j] = k % 10;
k = k *10/100;
}
for (;j < l0;j++) {
k = k + rode[j];
rode[j] = k % 10;
k = k*10/100;
}
if (k!=0)
rode[j++] = k;
rode[j] = '\0';
ll = j;
}
};
Node s[Max];
int main() {
int l,n,i;
int j,k,m,tt=1;
cin>>n>>m;
for (j = 1;j <= n;++j) {
cin>>a[j];
}
for (i = 0;i < m;++i) {
cin>>j>>k;
map_[j].push_back(k);
num[k]++;
}
for (j = 1;j <n+1;j++)
if (!num[j]) {
que.push(j);
zz[j] = a[j];
s[j].rode[0] = tt;
s[j].ll = tt;
}
while (!que.empty()) {
k = que.front();
que.pop();
while (!map_[k].empty()) {
j = map_[k].back();
map_[k].pop_back();
num[j]--;
if (zz[k] + a[j] > zz[j])
{
s[j] = s[k];
zz[j] = zz[k] + a[j];
}
else
if (zz[k] + a[j] == zz[j])
s[j] += s[k];
if (!num[j])
que.push(j);
}
}
for (j = 1;j < n+1;j++)
if (num[j])
{
cout<<"0";
return 0;
}
Node ss;
int ee=0;
ee--;
for (j = 1;j < n+1;j++) {
if (ee < zz[j])
{
ss = s[j];
ee = zz[j];
}
else if (ee == zz[j])
{
ss += s[j];
}
}
cout<<ee<<endl;
l = ss.ll-1;
for (j = l;j >= 0;j--)
cout<<ss.rode[j];
}