数据结构第七次上机

7-1 序列调度 (100 分)

有一个N个数的序列A:1,2,……,N。有一个后进先出容器D,容器的容量为C。如果给出一个由1到N组成的序列,那么可否由A使用容器D的插入和删除操作得到。

输出格式

第1行,2个整数T和C,空格分隔,分别表示询问的组数和容器的容量,1≤T≤10,1≤C≤N。

第2到T+1行,每行的第1个整数N,表示序列的元素数,1≤N≤10000。接下来N个整数,表示询问的序列。

输出格式

T行。若第i组的序列能得到,第i行输出Yes;否则,第i行输出No,1≤i≤T。

输入样例

2 2
5 1 2 5 4 3
4 1 3 2 4

输出样例

No
Yes

分析

1.开始以为是使用单调栈求出长度最大的单调减区间,若大于栈的长度则不能产生,但实际情况是多样的,所以应该使用一个栈模拟数字进出,判断是否能够产生

代码

#include <iostream>
#include <stdio.h>
#include <stack>
using namespace std;
typedef struct point{
	int num;
	int poi;
} pointor;
struct que{
	int l;
	int r;
	int num;
};
stack<int> ll,rr;
pointor num[100005];

int main()
{
	int t,c,n,max=0;
	scanf("%d%d",&t,&c);
	for(int i=0;i<t;i++)
	{
		scanf("%d",&n);
		for(int j=0;j<n;j++)
		{
			scanf("%d",&num[j].num);
			num[j].poi=i;
		}
		for(int j=1,k=0;k<n;)
		{
			ll.push(j);
			while(!ll.empty()&&ll.top()==num[k].num) 
			{
				ll.pop();k++;
			}
			if(j<n) j++;
			if(ll.size()>=c) break;		
		}
		if(ll.empty()) printf("Yes\n");
		else printf("No\n") ;
		while(!ll.empty()) ll.pop();
  	}
}


7-2 最大最小差 (100 分)

对n 个正整数,进行如下操作:每一次删去其中两个数 a 和 b,然后加入一个新数:a*b+1,如此下去直到 只剩下一个数。所有按这种操作方式最后得到的数中,最大的为max,最小的为min,计算max-min。

输出格式

第1行:n,数列元素的个数,1<=n<=16。

第2行:n 个用空格隔开的数x,x<=10

输出格式

1行,所求max-min。

输入样例

3
2 4 3

输出样例

2

分析

1.使用类似haffman算法,一个每次取最小,一个每次取最大。
2.取法符合贪心算法。

7-3 二叉树最短路径长度 (100 分)

给定一棵二叉树T,每个结点赋一个权值。计算从根结点到所有结点的最短路径长度。路径长度定义为:路径上的每个顶点的权值和。

输出格式

第1行,1个整数n,表示二叉树T的结点数,结点编号1…n,1≤n≤20000。

第2行,n个整数,空格分隔,表示T的先根序列,序列中结点用编号表示。

第3行,n个整数,空格分隔,表示T的中根序列,序列中结点用编号表示。

第4行,n个整数Wi,空格分隔,表示T中结点的权值,-10000≤Wi≤10000,1≤i≤n。

输出格式

1行,n个整数,表示根结点到其它所有结点的最短路径长度

输入样例

4
1 2 4 3
4 2 1 3
1 -1 2 3

输出样例

1 0 3 3

分析

1.根到任何一个节点的路只有一条,所以本题不需要使用图的算法,使用树的遍历加回溯法存储路径长度
2.先序中序建树的算法要以先序为主,辅助使用中序确定位置

代码

#include <stdio.h>
#include <stack>
using namespace std;
struct mid{
int num;
int w;
struct mid *left ;
struct mid *right;
};
typedef struct mid tree;
stack<int> path;
int a[50000],b[50000],w[50000];
int ii;
//先序中序建树 
void build(tree *&t, int n)//ii初始为0 
{
	if(ii==n) return ;
	t=new tree;
	t->num=a[ii] ;
	t->left=NULL;
	t->right=NULL;
	int j;
	for(j=0;j<n;j++)
	{
		if(a[ii]==b[j])
		{
			b[j]=0;
			for(int k=j-1;k>=0;k--)
			{
				if(b[k]==0) break;
				if(b[k]==a[ii+1])
				{
					ii++;
					build(t->left,n);
					break;
				}
			}
			break;
		}
	}
	for(int k=j+1;k<n;k++)
	{
		if(b[k]==0) break;
		if(b[k]==a[ii+1])
		{
			ii++;
			build(t->right,n);
		}
	}
}//先序中序建树 end 
long long len[50000];
void preorder(tree *t,long long all)
{
	if(t==NULL) return ; 
	all+=w[t->num];
	len[t->num]=all; 
	//遍历左子树
	preorder(t->left,all);
	preorder(t->right,all); 
}
int main()
{
	int n;
	scanf("%d",&n);
	for(int i=0;i<n;i++)
	{
		scanf("%d",&a[i]);
	}
	for(int i=0;i<n;i++)
	{
		scanf("%d",&b[i]);
	}
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&w[i]);
	}
	tree *root;
	build(root,n);
	preorder(root,0);
	for(int i=1;i<=n;i++) 
	{
		printf("%lld",len[i]);
		if(i!=n) printf(" "); 
	}
}

7-4 方案计数 (100 分)

组装一个产品需要 n 个零件。生产每个零件都需花费一定的时间。零件的生产可以并行进行。有些零件的生产有先后关系,只有一个零件的之前的所有零件都生产完毕,才能开始生产这个零件。如何合理安排工序,才能在最少的时间内完成所有零件的生产。在保证最少时间情况下,关键方案有多少种,关键方案是指从生产开始时间到结束时间的一个零件生产序列,序列中相邻两个零件的关系属于事先给出的零件间先后关系的集合,序列中的每一个零件的生产都不能延期。

输入格式

第1行,2个整数n和m,用空格分隔,分别表示零件数和关系数,零件编号1…n,1≤n≤10000, 0≤m≤100000 。

第2行,n个整数Ti,用空格分隔,表示零件i的生产时间,1≤i≤n,1≤Ti≤100 。

第3到m+2行,每行两个整数i和j,用空格分隔,表示零件i要在零件j之前生产。

输出格式

第1行,1个整数,完成生产的最少时间。

第2行,1个整数,关键方案数,最多100位。

如果生产不能完成,只输出1行,包含1个整数0

输入样例

4 4
1 2 2 1
1 2
1 3
2 4
3 4

输出样例

4
2

分析

1.题中给出的是AOV,需要加入虚汇点将点权推到边权上,将AOV网构建成AOE网,求ve和vl数组,当两者相等时该点位于关键路径上。
2.使用广搜求关键路径个数,任意一个点后继的为所有关键点都代表着不同的关键路径,最后沿路相乘得到所有的方案个数。

代码

#include<iostream>
#include<vector>
#include<queue>
using namespace std;
int rdu[10005],vl[10005], ve[10005];
queue<int>que;
vector<int>edge[10005];
class node {
public:
	int num[105],len;
	void operator =(const node& edge) {
		for (int i = 0; i < 105; ++i)
			num[i] = edge.num[i];
		len = edge.len;
	}
	void operator +=(const node& edge) {//高精度加法
		int i, len1, jwei = 0, len0, l0;
		len1 = edge.len;
		if (this->len < len1) 
		{ 
		len0 = this->len;
		l0 = len1;
		}
		else 
		{ 
			len0 = len1; 
			l0 = this->len;
		}
		for (i = 0; i < len0; ++i) 
		{
			jwei = num[i] + edge.num[i] + jwei;
			num[i] = jwei % 10;
			jwei/=10;
		}
		for (; i < l0; ++i) {
			jwei = jwei + num[i];
			num[i] = jwei % 10;
			jwei /= 10;
		}
		if (jwei)num[i++] = jwei;
		jwei = 0;
		num[i] = '\0';
		this->len = i;
	}

};
node num[10005];
int main() {
	int i, from, to,n, m;
	scanf("%d%d", &n, &m);
	for (i = 1; i <= n; ++i) {
		scanf("%d", &ve[i]);
	}
	for (i = 0; i < m; ++i) {
		scanf("%d%d", &from, &to);
		edge[from].push_back(to);
		rdu[to]++;
	}
	i = 1;
	while (i <= n)
	{
		if (!rdu[i]) {
			que.push(i);
			vl[i] = ve[i];
			num[i].num[0] = 1;
			num[i].len = 1;

		}
		i++;
	}
	while (!que.empty()) 
	{
		to = que.front(); 
		que.pop();
		while (!edge[to].empty()) {
			from = edge[to].back(); edge[to].pop_back();
			rdu[from]--;
			if (vl[to] + ve[from] > vl[from])
			{
				num[from] = num[to];
				vl[from] = vl[to] + ve[from];
			}
			else if (vl[to] + ve[from] == vl[from])num[from] += num[to];
			if (!rdu[from]) que.push(from);
		}

	}
	node ans; int count = -1;
	i = 1;
	while (i <= n)
	{
		if (rdu[i])
		{
			printf("0"); return 0;
		}
		i++;
	}
	for (i = 1; i <= n; ++i) 
	{
		if (count == vl[i])  ans += num[i];
		else if (count < vl[i])
		{
			ans = num[i];
			count = vl[i];
		}
	}
	printf("%d\n", count);
	for (i = ans.len-1; i >= 0; i--) printf("%d", ans.num[i]);
	return 0;
}
#include <stdio.h>
#include <iostream>
#include <vector>
#include <stack>
#include <queue>
#include <string.h>
using namespace std;
typedef struct edge {
	int ii;
	int cost;
	struct edge* next;
}  edge;
typedef struct vertex {
	int ii;
	int rdu,cdu,cost; 
	struct edge* next;
}vertex;
typedef struct graph {
	int vv, ee;
	vector<vertex> verlist;
}graph;
graph* g = new graph;

struct cmp{
	bool operator()(int a,int b)
	{
		return a>b;
	}
};
queue<int>qq;

int vis[100005];
int ve[100005],vl[100005];
int poi[10000],poi_i; 
int count[100005];//结点个数 
priority_queue<int,vector<int>,cmp> tt;
void tope()
{
	//for (int i = 1; i <=g->vv; i++)
	//	count[i] = 0;
	for (int i = 0; i < g->vv; i++)
	{
		edge* p;
		p = g->verlist[i].next;
		for (p; p; p = p->next)
		{
			count[p->ii]++;
		}
	}
	for (int i = 1; i <= g->vv; i++) 
		if (count[i]==0) 
		{
			//ve[i]=g->verlist[i-1].cost;
			tt.push(i);
			poi[poi_i++]=i;
		}
		
	for (int i = 1; i <=g->vv; i++)
	{
		if(tt.empty()) return ;
		int v = tt.top();
		tt.pop();
		for (edge* p = g->verlist[v-1].next; p; p = p->next)
		{
			count[p->ii]--;
			if (count[p->ii] == 0) 
			{
				tt.push(i);
				poi[poi_i++]=i;
			}
		}
		
	}
}
void fanxu(char num0[],char cpy0[])
{
	int len,i,j;
	len=strlen(num0);
	for(i=0,j=len-1;i<len;i++,j--)
	{
		cpy0[i]=num0[j];
	}
	cpy0[len]='\0';
	strcpy(num0,cpy0);
}
void Add(char *a)

{
	char c[1000],b[10]={'1'};
	int i,j,len_a,len_b,bwei=0,jwei=0;
	int num;
		fanxu(a,c);
		len_a=strlen(a);len_b=strlen(b);
		for(i=0;i<len_a&&i<len_b;i++)
		{
			bwei=jwei+(a[i]-'0')+(b[i]-'0');
			if(bwei>=10) 
			{
				jwei=1;
				bwei-=10;
			}
			else jwei=0;
			c[i]=bwei+'0';
		}
		for(;i<len_a;i++)
		{
			bwei=a[i]+jwei-'0';
			if(bwei>=10) 
			{				
				jwei=1;
				bwei-=10;
			}
			else jwei=0;
			c[i]=bwei+'0';
		}
		if(len_b>len_a)
		{
			for(;i<len_b;i++)
			{
				bwei=b[i]+jwei-'0';
				if(bwei>=10) 
				{
					jwei=1;
					bwei-=10;
				}
				else jwei=0;
				c[i]=bwei+'0';			
			}	
		} 
		if(jwei==1) c[i++]='1'; 
		c[i]='\0';
		fanxu(c,a);
		strcpy(a,c);
		return ;
}
char max1[105];
void DFS(int v)
{
	if(v==g->vv) 
	{
		Add(max1);
		printf("%s", max1); 
		return ;
	}
	vis[v] = 1;
	for (edge* pp = g->verlist[v - 1].next; pp; pp = pp->next)
	{
		if (!vis[pp->ii])
		{
			DFS(pp->ii);
		}
	}
	
}

int main()
{
	
	scanf("%d%d",&g->vv,&g->ee);
	for (int i = 1; i <= g->vv; i++)
	{
		int cost;
		scanf("%d",&cost);
		vertex* p = new vertex;
		p->ii = i ;
		p->next = NULL;
		p->cost=cost;
		p->cdu=p->rdu=0;
		g->verlist.push_back(*p);
	
	}
	for (int i = 0; i < g->ee; i++)
	{
		int m, n;
		scanf("%d%d",&m,&n); 
		g->verlist[m-1].cdu++;
		g->verlist[n-1].rdu++;
		edge* q = new edge;
		q->ii = n;
		q->cost=g->verlist[m-1].cost;
		q->next = NULL;
		if (!g->verlist[m-1].next)
		{
			g->verlist[m-1].next = q;
		}
		else
		{
			edge* head = g->verlist[m-1].next;
			while (head->next)
			{
				head = head->next;
			}
			head->next = q;
		}
	}
	vertex* p = new vertex;
	p->ii = 0;
	p->next = NULL;
	g->verlist.push_back(*p);
	/*p = new vertex;
	p->ii = n+1;*/
	for(int i=0;i<g->vv;i++)
	{
		if(g->verlist[i].cdu==0)
		{
		edge* q = new edge;
		q->ii = g->vv+1;
		q->cost = g->verlist[i].cost;
		q->next = NULL;
		if (!g->verlist[i].next)
		{
			g->verlist[i].next = q;
		}
		else
		{
			edge* head = g->verlist[i].next;
			while (head->next)
			{
				head = head->next;
			}
			head->next = q;
		}
		}
		if(g->verlist[i].rdu==0)
		{
			Add(max1);
		}
	}
	tope();
	g->vv++;
	//初始化省略 
	for(int i=1;i<=g->vv;i++)
	{
		for(edge *p=g->verlist[i-1].next;p;p=p->next)
		{
			if(ve[i]+p->cost>ve[p->ii]) 
			ve[p->ii]=ve[i]+p->cost;	 
		}
	}
	for(int i=1;i<=g->vv;i++) vl[i]=ve[i];
	for(int i=g->vv;i>=1;i--)
	{
		for(edge *p=g->verlist[i-1].next;p;p=p->next)
		{
			if(vl[p->ii]-p->cost<vl[i])
			vl[i]=vl[p->ii]-p->cost;
		}
	}
	char max[105],count[105];
	memset(max,0,sizeof(char)*105);
	qq.push(1);
	vis[1]=1;

	while (!qq.empty())
	{
		memset(count,0,sizeof(char)*105);
		int cont = 0;
		int v = qq.front();
		qq.pop();
		edge* p = g->verlist[v - 1].next;
		for (p; p; p = p->next)
		{
			if (vis[p->ii] == 0)
			{
				vis[p->ii] = 1;
				qq.push(p->ii);
				if (ve[p->ii] == vl[p->ii])
				{
					
					Add(count);
				}
			}
		}
		if (strcmp(max,count)<0) strcpy(max,count);
	}
	printf("%d\n", vl[g->vv] );
	if(strcmp(max,max1)>=0)printf("%s", max);
	else printf("%s", max1);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值