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);
}