PekingOJ 1363&1125&1564&1511

本文最后更新于:5 年前

这四题都是easy难度的,但还是很适合初学者好好练习的!【老师布置的题目原来不是按难度排序的..】

一、Stack

就是给定一个入栈顺序,去判断给定的出栈顺序可不可能实现
Sample Input

5
1 2 3 4 5
5 4 1 2 3
0
6
6 5 4 3 2 1
0
0
Sample Output

Yes
No

Yes

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
#include <iostream>
#include <stack>
using namespace std;
stack<int> mystack;
void Stackjudge(int q[1000],int num){
while(!mystack.empty()){
mystack.pop();
}
int i,j;
int flag1=0;
int test;
int first=0;
for(i=1;i<num+1;i++){ //算出第一位
if(i!=q[0]){
mystack.push(i);
}
else{
first=i;
break;
}
}
if(!first){
cout<<"No"<<endl;
return;
}
for(j=1;j<num;j++){
if(q[j]>q[j-1]){
for(i=first+1;i<num+1;i++){
mystack.push(i);
if(i==q[j]){
mystack.pop();
first=i;
flag1=1;
}
}
if(!flag1){
cout<<"No"<<endl;
return;
}
}
flag1=0;

if(q[j]<q[j-1]){
test=mystack.top();
if(test==q[j]){
mystack.pop();
}
else{
cout<<"No"<<endl;
return;
}
}
}
std::cout<<"Yes"<<endl;
}
int main ()
{
int i;
int Q[1000];
while(1){
int num;
cin>>num;
if(num==0){
break;
}
while(1){
cin>>Q[0];
if(Q[0]==0){
break;
}
for(i=1;i<num;i++){
cin>>Q[i];
}
Stackjudge(Q,num);
}
cout<<endl;
}
return 0;
}

二、最短路径

股票经纪人对谣言的过分反应是周知的。你受雇找一种在股市中散布谣言的方法,使之以最快的速度传播给所有的人。
你必须把谣言先传给一个最合适的人
输入:
3 //三个人 2 2 4 3 5 //1号人有2个联系人,和2号花时间4,和3号花时间5 2 1 2 3 6 //2号人…… 2 1 2 2 2 5 3 4 4 2 8 5 3 1 5 8 4 1 6 4 10 2 7 5 2
输出:
3 2 //先传给3号,最多花时间2 3 10

分析:任意两点间求出最短路径(Floyd?) 。
找点:到任意点都有路径。“谣言传播”总耗时等于这些路径的最大值。
目标:使这个最大值最小的某个点。

这题不太想做…直接给floyd的算法吧

1
2
3
4
5
6
7
for(k=0;k<n;k++)
for(i=0;i<n;i++)
for( j=0;j<n;j++)
if (d[i][j]>d[i][k]+d[k][j])
d[i][j]=d[i][k]+d[k][j];
//d[i][j]=Min(d[i][j], d[i][k]+d[k][j])

三、DFS

Sum it up
求出所有可能的加法可能
Sample Input

4 6 4 3 2 2 1 1
5 3 2 1 1
400 12 50 50 50 50 50 50 25 25 25 25 25 25
0 0

Sample Output

Sums of 4:
4
3+1
2+2
2+1+1
Sums of 5:
NONE
Sums of 400:
50+50+50+50+50+50+25+25+25+25
50+50+50+50+50+25+25+25+25+25+25

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include <iostream>
#include <stdio.h>
#include <algorithm>

using namespace std;
int n,t,a[13],b[13],flag=1;

void dfs(int num,int k,int sum)
{
if(sum==0){
printf("%d",b[0]);
for(int i=1;i<num;i++)
printf("+%d",b[i]);
cout<<endl;
flag=0;
}
for(int i=k;i<n;i++){
if((i==k||a[i]!=a[i-1])&&sum-a[i]>=0){ //去重
b[num]=a[i];
dfs(num+1,i+1,sum-a[i]);
}
}
}


int main()
{
while(1){
cin>>t>>n;
if(t==0&&n==0)
break;
for(int i=0;i<n;i++)
cin>>a[i];
printf("Sums of %d:\n",t);
dfs(0,0,t);
if(f) {
printf("NONE\n");
}
}
return 0;
}



四、Dijkstra变形题

POJ - 1511 Invitation Cards(Dijkstra变形题)
因为不太熟悉C++的容器,并且本题要求存储的数据量极大,二重矩阵十分浪费空间且运行时间不过关,需要使用其他的数据结构,所以参考了以下博客。
这道题主要就让自己知道怎样构建“数组链表”
这里就提取几行关键的数据结构代码,博客中没有注释,我稍微写了一点点注释。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
vector<edge> map[maxn];   //vector容器
typedef pair<int,int> P;

map[a].push_back(edge(a,b,c)); //将一条边的信息链接在map[起始点]的最后面

priority_queue<P,vector<P>,greater<P> > Q; //dijkstra算法中构建Q优先队列
//<Type,Container,Function>

Q.push(P(0,1)); //源点是1,dist[1]=0
while(!Q.empty()){
int v=Q.top().second; // 这里开始看编号为v的这个点
Q.pop();
if(visited[v]) continue; //已经访问过的点就不再考虑了,这也就是为什么一旦边的权值有负数,此算法就没用了,因为还有可能从原来的路径绕路得到最短路径。有负值时我们采用Bellmam-Ford算法。
visited[v]=true;
for(int i=0;i<map[v].size();i++){ //这个size就是从v这个点有多少个边,遍历这些边,去做最短路径的替换
edge e=map[v][i];
if(dist[e.t]>dist[v]+e.c){
dist[e.t]=dist[v]+e.c;
Q.push(P(dist[e.t],e.t));
}
}
}

当然本题还要求各个点到源点的最短距离,这时我们可以用一个思路:反图,我们将原图中的所有边的方向反转,此时对远点使用Dijkstra算法则可得到其余各点到源点的最短距离。 大家自己画张图就可以很好得理解啦!


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!