用C还是C++自己注意一下
实例1.1 最大子列和问题 (20分)
#include <iostream>
#include <cstdio>
using namespace std;
int main()
{
int n,d,sum=0,ans=0;
cin>>n;
for(int i=0;i<n;i++)
{
cin>>d;
sum+=d;
if(sum<0)
sum=0;
if(sum>ans)
ans=sum;
}
cout<<ans;
return 0;
}
习题2.1 简单计算器 (20分)
#include <stdio.h>
#include <stdlib.h>
int main() {
int result, a1, a2;
char b;
scanf("%d", &a1);
result = a1;
while (1) {
scanf("%c", &b);
if (b == '=') {
printf("%d", result);
break;
}
scanf("%d", &a2);
if (b == '+') result = result + a2;
else if (b == '-') result = result - a2;
else if (b == '*') result = result * a2;
else if (b == '/') {
if (a2 == 0) {
printf("ERROR");
break;
}
else {
result = result / a2;
}
}
else {
printf("ERROR");
break;
}
}
return 0;
}
习题2.2 数组循环左移 (20分)
#include<stdio.h>
void turn(int *p , int i , int n );
int main()
{
int n,m;
scanf("%d %d",&n,&m);
if(m>=n)
m=m%n;
int i,a[n];
for(i=0;i<n;i++)
{ if(i!=n-1)
scanf("%d ",&a[i]);
else
scanf("%d",&a[i]);
}
turn(a,0,m);
turn(a,m,n+m);
turn(a,0,n);
for(i=0;i<n;i++)
{ if(!i)
printf("%d",a[i]);
else
printf(" %d",a[i]);
}
return 0;
}
void turn(int *p , int i , int n )
{
int t;
for(;i<n/2;i++)
{
t=*(p+i);
*(p+i)=*(p+n-i-1);
*(p+n-i-1)=t;
}
}
习题2.3 数列求和-加强版 (20分)
#include<stdio.h>
#define maxzie 100000
int sum( int a, int n , int *p);
int main()
{
int A,N,s[maxzie+1],count;
scanf("%d %d",&A,&N);
if(N!=0) //N=0的情况
{
count=sum(A,N,s);
for(count--;count>=0;count--) //低位在数组末尾
printf("%d",s[count]);
}
else printf("0");
}
int sum( int a, int n , int *p)
{
int i,m,remain=0,count=0;
for(i=0;i<n;i++)
{
m=a*(n-i)+remain;
p[i]=m%10;
remain=m/10;
count++; //count为数的位数
}
if(remain!=0)
{
p[i]=remain;
count++;
}
return count;
}
习题2.8 输出全排列 (20分)
#include <stdio.h>
#include<string.h>
int Mark[10];
int Element[10];
void dfs(int n,int pcur){
if(pcur==n){//递归出口
int i;
for(i=0;i<n;i++){
printf("%d",Element[i]);
}
printf("\n");
return;
}
else{
int j;
for(j=1;j<=n;j++){
//判断j是否被使用过;如若使用过,将不再放入Element[ ]数组中
if(!Mark[j]){
//放值
Element[pcur]=j;
//标记j已被使用
Mark[j]=1;
//递归,实现深搜
dfs(n,pcur+1);
//回溯部分,设置当前值并未被使用
Mark[j]=0;
}
}
}
}
int main(){
int n;
scanf("%d",&n);
memset(Mark,0,sizeof(Mark));
dfs(n,0);
return 0;
}
习题3.4 最长连续递增子序列 (20分)
#include <stdio.h>
#define MAXSIZE 100000
typedef struct Node{
int Data[MAXSIZE];
int size;
}Node, *List; /*传递结构指针效率高*/
List Read(List L);
void PrintSeq(List L);
int main(void){
Node node;
List L = &node;
L = Read(L);
PrintSeq(L);
return 0;
}
List Read(List L){
int n, i;
scanf("%d", &n);
L->size = n;
for(i=0; i<n; i++){
scanf("%d", &L->Data[i]);
}
return L;
}
void PrintSeq(List L){
int maxL, maxR, maxLen, l, r, len;
int i;
if(L->size==0)
return;
else{
maxL=maxR=0;
maxLen = 1;
}
l=r=0;
len = 1;
for(i=1; i<L->size; i++){
if(L->Data[i]>L->Data[i-1]){
r++;
len++;
}
else{ /*遇到非增长点更新*/
if(len>maxLen){
maxL = l;
maxR = r;
maxLen = len;
}
l=r=i;
len = 1;
}
}
if(len>maxLen){ /*遍历结束后再次判断以防遗漏*/
maxL = l;
maxR = r;
maxLen = len;
}
for(i=maxL; i<=maxR; i++){
if(i==maxL)
printf("%d", L->Data[i]);
else
printf(" %d", L->Data[i]);
}
}
习题3.6 一元多项式的乘法与加法运算 (20分)
#include <iostream>
#include <map>
#include <algorithm>
using namespace std;
struct poly
{
int a,b;
}r1[1000],r2[1000];
int ans[1000000],ant = 0;
int main()
{
int a,b,flag = 0,e;
cin>>a;
for(int i = 0;i < a;i ++)
{
cin>>r1[i].a>>r1[i].b;
}
cin>>b;
for(int i = 0;i < b;i ++)
{
cin>>r2[i].a>>r2[i].b;
}
map<int,int>p,q;
for(int i = 0;i < a;i ++)
{
for(int k = 0;k < b;k ++)
{
if(p[r1[i].b + r2[k].b] == 0)ans[ant ++] = r1[i].b + r2[k].b;
p[r1[i].b + r2[k].b] += r1[i].a*r2[k].a;
}
}
e = 0;
sort(ans,ans+ant);
for(int i = ant - 1;i >= 0;i --)
if(p[ans[i]])
{
e ++;
if(flag)cout<<' '<<p[ans[i]]<<' '<<ans[i];
else
{
cout<<p[ans[i]]<<' '<<ans[i];
flag = 1;
}
}
if(e == 0)cout<<0<<' '<<0;
cout<<endl;
ant = 0;
e = 0;
for(int i = 0;i < a;i ++)
{
if(q[r1[i].b] == 0)ans[ant ++] = r1[i].b;
q[r1[i].b] += r1[i].a;
}
for(int i = 0;i < b;i ++)
{
if(q[r2[i].b] == 0)ans[ant ++] = r2[i].b;
q[r2[i].b] += r2[i].a;
}
if(ant == 0)cout<<0<<' '<<0;
sort(ans,ans+ant);
flag = 0;
for(int i = ant - 1;i >= 0;i --)
if(q[ans[i]])
{
e ++;
if(flag)cout<<' '<<q[ans[i]]<<' '<<ans[i];
else
{
flag = 1;
cout<<q[ans[i]]<<' '<<ans[i];
}
}
if(e == 0)cout<<0<<' '<<0;
}
习题3.8 符号配对 (20分)
#include<stdio.h>
#define MaxSize 100
struct stack{
char elem[MaxSize];
int top;
};
typedef struct stack seqstack;
int push(seqstack *s,char c);
int pop(seqstack *s,char *x);
int gettop(seqstack *s,char *x);
void InitStack(seqstack *s);
int match(char c1,char c2);
void InitStack(seqstack *s)
{
s->top=-1;
}
int push(seqstack *s,char c)
{
if(s->top==MaxSize-1)
return 0;
else{
s->elem[++s->top]=c;
return 1;
}
}
int pop(seqstack *s,char *x){
if(s->top==-1)
return 0;
else{
*x=s->elem[s->top--];//这里用的*x
return 1;
}
}
int gettop(seqstack *s,char *x)
{
if(s->top==-1)
return 0;
else{
*x=s->elem[s->top];
return 1;
}
}
int main()
{
seqstack s;
char ch;
int i=0;
InitStack(&s);
char str[1000];
while(gets(str))
{
if(str[0]=='.'&&str[1]==0)//这里有个跳出循环
break;
for(i=0;str[i]!='\0';i++){
switch(str[i])
{
case '(':
case '{':
case '[':
push(&s,str[i]);
break;
case '/':
if(str[i+1]=='*'){
push(&s,str[i]);
push(&s,str[i+1]);
}
i+=1;
break;
case ')':
case '}':
case ']':
case '*':
if(s.top==-1)
{
printf("NO\n");
switch(str[i])
{
case ')':
printf("?-)");
break;
case '}':
printf("?-}");
break;
case ']':
printf("?-]");
break;
case '*':
if(str[i]=='*'&&str[i+1]=='/')
printf("?-*/");
break;
}
return 0;
}
else{
gettop(&s,&ch);
if(match(ch,str[i]))
{
pop(&s,&ch);
}
else if(str[i]=='*')//* 字符 做单独处理
{
if(ch=='*'&&str[i+1]=='/')// 是*/的符号
{
pop(&s,&ch);
pop(&s,&ch);
i++;
}
else//只是单一的 * 号
{
continue;
}
}
else
{
printf("NO\n");
switch(ch)
{
case '{':
printf("{-?");
break;
case '(':
printf("(-?");
break;
case '[':
printf("[-?");
break;
case '*':
printf("/*-?");
break;
}
return 0;
}
}
}
}
}
if(s.top==-1)
printf("YES\n");
else{
printf("NO\n");
switch(ch)
{
case '{':
printf("{-?");
break;
case '(':
printf("(-?");
break;
case '[':
printf("[-?");
break;
case '*':
printf("/*-?");
break;
}
return 0;
}
}
int match(char c1,char c2)
{
switch(c1)
{
case '(':
if(c2==')')
return 1;
else
return 0;
break;
case '[':
if(c2==']')
return 1;
else
return 0;
break;
case '{':
if(c2=='}')
return 1;
else
return 0;
break;
default:
return 0;
}
}
习题3.9 堆栈操作合法性 (20分)
#include<stdio.h>
typedef enum{false,true} bool;
bool Judge(int N);
int main()
{
int L;//number of line
int N;//max of stack
int flag=1;//adjust output
scanf("%d %d\n", &L, &N);
while (L--) {
if (Judge(N)) {
if (flag) flag = 0;
else printf("\n");
printf("YES");
}
else {
if (flag) flag = 0;
else printf("\n");
printf("NO");
}
}
return 0;
}
bool Judge(int N) {
char temp;//temp storage of getchar
int stack = 0;//number of stack
int flag = 1;//1-true,0-false
temp = getchar();//the first one
while (temp != '\n'&&temp != '\0') {
if (temp == 'S'&&stack<N) stack++;
else if (temp == 'S'&&stack == N) flag = 0;
else if (!stack) flag = 0;
else stack--;
temp = getchar();
}
if(stack) flag=0;
if (flag) return true;
else return false;
}
习题3.10 汉诺塔的非递归实现 (25分)
#include<stdio.h>
#include<stdlib.h>
typedef struct Node* pNode;
struct Node {
int cnt;
char start;
char pass;
char end;
};
typedef struct stack* pstack;
struct stack {
pNode data;
pstack next;
};
typedef struct list* plist;
struct list {
pstack head;
};
plist newlist(void);
pstack firststack(int N);
void pop(plist L);
void trinode(plist L);
int main()
{
int N, i, flag = 1;
scanf("%d", &N);
plist L = newlist();
L->head->next = firststack(N);
while (L->head->next) {
if (L->head->next->data->cnt==1) {
if (flag) flag = 0;
else printf("\n");
pop(L);
}
else {
trinode(L);
}
}
return 0;
}
plist newlist(void) {
plist L = (plist)malloc(sizeof(struct list));
L->head = (pstack)malloc(sizeof(struct stack));
L->head->next = NULL;
return L;
}
pstack firststack(int N) {
pstack S = (pstack)malloc(sizeof(struct stack));
S->next = NULL;
S->data = (pNode)malloc(sizeof(struct Node));
S->data->cnt = N;
S->data->start = 'a';
S->data->pass = 'b';
S->data->end = 'c';
return S;
}
void pop(plist L) {
printf("%c -> %c", L->head->next->data->start, L->head->next->data->end);
pstack p = L->head->next;
L->head->next = p->next;
free(p);
}
void trinode(plist L) {
pstack p = L->head->next;
p->data->cnt--;
char temp = p->data->start;
p->data->start = p->data->pass;
p->data->pass = temp;
pstack p1 = (pstack)malloc(sizeof(struct stack));
pstack pn = (pstack)malloc(sizeof(struct stack));
pn->next = p1;
p1->next = p;
L->head->next = pn;
pn->data = (pNode)malloc(sizeof(struct Node));
p1->data = (pNode)malloc(sizeof(struct Node));
pn->data->cnt = p->data->cnt;
p1->data->cnt = 1;
p1->data->start = p->data->pass;
p1->data->pass = p->data->start;
p1->data->end = p->data->end;
pn->data->pass = p1->data->end;
pn->data->end = p1->data->pass;
pn->data->start = p1->data->start;
}
习题3.11 表达式转换 (25分)
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct snode *stack;
struct snode{
char ch[20];
int top;
};
stack CreateStack(); //创建堆栈
void push(stack s,char c); //入栈
char pop(stack s); //出栈
int main()
{
char ch1[150]; //用来存储符号优先级
ch1['(']=0;
ch1['+']=1;
ch1['-']=1;
ch1['*']=2;
ch1['/']=2;
char s[21]; //用来存储中缀表达式
scanf("%s",s);
int l=strlen(s);
stack st=CreateStack();
int flag=0; //该标志位用来控制格式输出
for(int i=0;i<l;i++) //遍历中缀表达式符号
{
if(s[i]=='(')
{
push(st,s[i]);
}
else if(s[i]==')')
{
char t;
t=pop(st);
while(t!='(')
{
printf(" %c",t);
t=pop(st);
}
flag=1;
}
else if(s[i]=='+'||s[i]=='-'||s[i]=='*'||s[i]=='/')
{
if(s[i]=='+'&&(s[i-1]=='('||i==0));//如果这个+表示正号,不进行操作
else if(s[i]=='-'&&(s[i-1]=='('||i==0))//如果这个-表示负号,直接输出
{
printf("-");
}
else if(ch1[s[i]]>ch1[st->ch[st->top]]||st->top==-1)
{
push(st,s[i]);
flag=1;
}
else
{
printf(" %c",pop(st));
while(ch1[s[i]]<=ch1[st->ch[st->top]]&&st->top!=-1)
{
printf(" %c",pop(st));
}
push(st,s[i]);
flag=1;
}
}
else //运算数直接输出(包含小数.)
{
if(flag)
{
printf(" ");
flag=0;
}
printf("%c",s[i]);
}
}
while(st->top!=-1)//输出堆栈中剩余的符号
{
printf(" %c",pop(st));
}
return 0;
}
stack CreateStack()
{
stack s=(stack)malloc(sizeof(struct snode));
s->top=-1;
return s;
}
void push(stack s,char c)
{
(s->top)++;
s->ch[s->top]=c;
}
char pop(stack s)
{
return s->ch[(s->top)--];
}
练习4.1 根据后序和中序遍历输出先序遍历 (25分)
#include<stdio.h>
#include<string.h>
int m[10000];
int e[10000];
int str[100000];
void find(int root,int start,int end);
int main()
{
int n,i;
scanf("%d",&n);
for(i=0;i<n;i++)
{
scanf("%d",&e[i]);
}
for(i=0;i<n;i++)
{
scanf("%d",&m[i]);
}
find(n-1,0,n-1);
printf("Preorder: ");
for(i=0;i<n-1;i++)
printf("%d ",str[i]);
printf("%d",str[n-1]);
return 0;
}
int sign=0;
void find(int root,int start,int end)
{
if(start > end)
return;
int i = start;
while(i<end && m[i]!=e[root])
i++;
str[sign++]=m[i];
find(root-(end-i+1), start, i-1);
find(root-1, i+1, end);
}
练习4.2 平衡二叉树的根 (25分)
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
using namespace std;
struct AVLNode{
int Data; /*结点数据*/
AVLNode * Left; /*指向左子树*/
AVLNode * Right;/*指向右子树*/
int Height; /*树高*/
};
typedef struct AVLNode * Position;/*定义结构体指针别名为Position*/
typedef Position AVLTree;
int Max(int a, int b)
{
return a > b ? a:b;
}
int GetHeight(AVLTree A)
{/*获取结点A的高度*/
int L,R;
if(A){
L=GetHeight(A->Left);/*求左子树的高度*/
R=GetHeight(A->Right);/*求右子树的高度*/
return L>R ? (L+1):(R+1);
}
else return 0;/*空树高度为0*/
}
AVLTree SingleLeftRotation(AVLTree A)
{/*左单旋,顺时针*/
AVLTree B=A->Left;
A->Left = B->Right;
B->Right = A;
A->Height = Max(GetHeight(A->Left), GetHeight(A->Right)) + 1;
B->Height = Max(GetHeight(B->Left), A->Height) + 1;
return B;
}
AVLTree SingleRightRotation(AVLTree A)
{
AVLTree B=A->Right;
A->Right = B->Left;
B->Left = A;
A->Height = Max(GetHeight(A->Left), GetHeight(A->Right)) + 1;
B->Height = Max(GetHeight(B->Right), A->Height) + 1;
return B;
}
AVLTree DoubleLeftRightRotation(AVLTree A)
{
A->Left=SingleRightRotation(A->Left);
return SingleLeftRotation(A);
}
AVLTree DoubleRightLeftRotation(AVLTree A)
{
A->Right=SingleLeftRotation(A->Right);
return SingleRightRotation(A);
}
AVLTree Insert(AVLTree T, int X)
{/*将X插入AVL树T中,并且返回调整后的AVL树*/
if(!T){ /*若插入空树,则新建包含一个结点的树*/
//T=(AVLTree)malloc(sizeof(struct AVLNode));
T=new AVLNode;
T->Data = X;
T->Height = 1;
T->Left = T->Right = NULL;
} /*if(插入空树)结束*/
else if( X < T->Data ){
/*插入T的左子树*/
T->Left = Insert ( T->Left ,X);
/*如果需要左旋*/
if(GetHeight(T->Left)-GetHeight(T->Right)==2)
if(X<T->Left->Data)
T=SingleLeftRotation(T); /*左单旋*/
else
T=DoubleLeftRightRotation(T); /*左-右双旋*/
} /*else if(插入左子树)结束*/
else if (X>T->Data){
/*插入T的右子树*/
T->Right = Insert ( T->Right ,X);
/*如果需要右旋*/
if(GetHeight(T->Left)-GetHeight(T->Right)==-2)
if(X>T->Right->Data)
T=SingleRightRotation(T); /*右单旋*/
else
T=DoubleRightLeftRotation(T); /*右-左双旋*/
} /*else if(插入右子树)结束*/
/*else X==T->Data, 无需插入 */
/*别忘了更新树高*/
T->Height = Max(GetHeight(T->Left), GetHeight(T->Right))+1;
return T;
}
int main(){
int n,x;
AVLTree A=NULL;
scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%d",&x);
A=Insert(A,x);
}
printf("%d\n",A->Data);
return 0;
}
练习4.3 堆中的路径 (25分)
#include <cstdio>
#include <cstdlib>
#define MAX 1001
#define MINH -10001
int H[MAX],size;
void Create() { //建立空堆
size = 0;
H[0] = MINH; //设置哨兵
}
void insert(int X) { //把X放于最后逐个与它的父节点进行比较,很巧妙!
int i;
for(i = ++size; H[i/2] > X; i /= 2)
H[i] = H[i/2];
H[i] = X;
}
int main() {
int N, M, temp, j;
scanf("%d%d", &N, &M);
Create();
for(int i = 0; i < N; i++) {
scanf("%d", &temp);
insert(temp);
}
for(int i = 0; i < M; i++) {
scanf("%d", &j);
printf("%d", H[j]);
while(j > 1) { //每次坐标除以2得到它的父节点,并输出就是路径
j /= 2;
printf(" %d", H[j]);
}
printf("\n");
}
return 0;
}
习题4.5 顺序存储的二叉树的最近的公共祖先问题 (25分)
#include <cstdio>
using namespace std;
int k;
int findroot(int a[],int x,int y)
{
while(1)
{
if(x>y)
{
x/=2;
}
else
{
y/=2;
}
if(x==y)
{
k=x;
return a[x];
}
}
}
int main()
{
int n;
while(~scanf("%d",&n))
{
k=-1;
int a[1010];
for(int i=1; i<=n; i++)
scanf("%d",&a[i]);
int x,y;
scanf("%d %d",&x,&y);
int ans=findroot(a,x,y);
if(x==y)
{
printf("%d %d\n",x,a[x]);
}
else if(a[x]==0)
{
printf("ERROR: T[%d] is NULL\n",x);
}
else if(a[y]==0)
{
printf("ERROR: T[%d] is NULL\n",y);
}
else
{
printf("%d %d\n",k,ans);
}
}
}
习题5.13 词频统计 (30分)
#include <iostream>
#include <map>
#include <set>
#include <string>
using namespace std;
struct Node {
string str;
int count;
bool operator<(const Node& s)const {
return count == s.count ? str<s.str : count>s.count;
}
};
int main() {
set<Node>st;
map<string, int>mp;
string s;
char c;
while (scanf("%c", &c) && c != '#') {
if (isalnum(c) || c == '_') {
if (isalpha(c))
c = tolower(c);
s += c;
}
else if (s.size()) {
if (s.size() > 15)
s = s.substr(0, 15);
mp[s]++;
s.clear();
}
}
for (auto& it : mp)
st.insert({ it.first,it.second });
int cnt = st.size();
cout << cnt << endl;
cnt /= 10;
for (auto& it : st) {
cout << it.count << ":" << it.str << endl;
if (!--cnt)
break;
}
return 0;
}
实例6.1 六度空间 (30分)
#include <stdio.h>
#include <stdbool.h>
#define SIX 6
int Graph[1001][1001], Queue[1001], N;
bool Visited[1001];
void Reset()
{
int i;
for (i = 1; i <= N; i++) {
Visited[i] = false;
}
}
void Read()
{
int M, i, j;
scanf("%d %d", &N, &M);
for (i = 1; i <= N; i++) {
Visited[i] = false;
for (j = 1; j <= N; j++) {
Graph[i][j] = 0;
}
}
while (M--) {
scanf("%d %d", &i, &j);
Graph[i][j] = 1;
Graph[j][i] = 1;
}
}
int BFS(int V)
{
int Front, Rear, Vertex, Tail, Last, Count, Level;
int i;
if (!Visited[V]) {
Front = Rear = 0;
Level = 0, Count = 1, Last = V;
Visited[V] = true;
Queue[Rear++] = V;
while (Front != Rear) {
Vertex = Queue[Front++];
for (i = 1; i <= N; i++) {
if (Graph[Vertex][i] && !Visited[i]) {
Visited[i] = true;
Queue[Rear++] = i;
Tail = i;
Count++;
}
}
if (Vertex == Last) {
Level++;
Last = Tail;
}
if (Level == SIX) {
break;
}
}
}
return Count;
}
void Print(int V, int Count)
{
printf("%d: %.2f%%\n", V, (double)(Count * 100) / (double) N);
}
void Compute()
{
int i;
for (i = 1; i <= N; i++) {
Print(i, BFS(i));
Reset();
}
}
int main()
{
//freopen("E:in.txt", "r", stdin);
Read();
Compute();
}
练习7.1 排序 (25分)
#include<stdio.h>
#include<stdlib.h>
void InsertationSort(int A[],int n);
void PrecDown(int A[],int p,int n);
void HeapSort(int A[],int n);
int main()
{
int N,*A;
scanf("%d",&N);
A=(int *)malloc(sizeof(int)*N);
for(int i=0;i<N;i++)
{
scanf("%d",&A[i]);
}
if(N<100)
{
InsertationSort(A,N);
}
else
{
HeapSort(A,N);
}
printf("%d",A[0]);
for(int i=1;i<N;i++)
{
printf(" %d",A[i]);
}
return 0;
}
void InsertationSort(int A[],int n)
{
int i,j;
for(i=1;i<n;i++)
{
int temp=A[i];
for(j=i;j>0&&A[j-1]>temp;j--)
{
A[j]=A[j-1];
}
A[j]=temp;
}
}
//下滤
void PrecDown(int A[],int p,int n)
{
int parent,child,X;
X=A[p];
for(parent=p;(2*parent+1)<n;parent=child)
{
child=2*parent+1;
if(A[child]<A[child+1]&&child!=n-1)
{
child++;
}
if(X>=A[child])
{
break;
}
else
{
A[parent]=A[child];
}
}
A[parent]=X;
}
void HeapSort(int A[],int n)
{
for(int i=n/2-1;i>=0;i--)//建立最大堆
{
PrecDown(A,i,n);
}
//把最大值换到最后
for(int i=n-1;i>0;i--)
{
int temp;
temp=A[0];
A[0]=A[i];
A[i]=temp;
PrecDown(A,0,i);
}
}
习题8.1 银行排队问题之单队列多窗口服务 (25分)
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct
{
double start;
double ends;
double wait;
}Person;
typedef struct
{
int num;
Person List[1005];
}Window;
int main()
{
int n, k;
double s, e, time = 0, Min_time = 0, Maxtime = 0;
Window all[15];
Person store[10000];
scanf("%d", &n);
for(int i = 0; i < n; i++)
{
scanf("%lf %lf", &s, &e);
if(e > 60){e = 60;}
store[i].start = s, store[i].ends = e + s;
}
scanf("%d", &k);
for(int i = 0 ; i < k; i++)
{
all[i].num = 0;
all[i].List[0].ends = 0;
}
for(int i = 0; i < n; i++)
{
double mintime = 0;
int place = 0;
for(int j = 0; j < k; j++)
{
if(!j)
{
int num = all[j].num - 1;
mintime = all[j].List[num].ends - store[i].start;
if(mintime < 0)
{
mintime = 0;
}
place = j;
//printf("%lf %d %lf\n", mintime, all[j].List[num].ends - store[i].start, place);
//printf("%lf %lf\n", all[j].List[num].ends, store[i].start);
}
else
{
int num = all[j].num - 1;
double time = all[j].List[num].ends - store[i].start;
if(time < 0)
{
time = 0;
}
if(mintime > time)
{
mintime = time;
place = j;
}
//printf("++%lf %d %lf\n", mintime, all[j].List[num].ends - store[i].start, place);
//printf("%lf %lf\n", all[j].List[num].ends, store[i].start);
}
//printf("%lf %d\n", mintime, place);
}
int num = all[place].num;
all[place].num++;
//printf("%d %d\n", place, all[place].num);
all[place].List[num].start = store[i].start + mintime;
all[place].List[num].wait = mintime;
all[place].List[num].ends = store[i].ends + mintime;
//printf("%lf %lf\n", all[place].List[num].ends, all[place].List[num].start);
if(!i)
{
Min_time = mintime;
Maxtime = store[i].ends + mintime;
}
else
{
if(mintime > Min_time)
{
Min_time = mintime;
}
if(Maxtime < store[i].ends + mintime)
{
Maxtime = store[i].ends + mintime;
}
}
time += mintime;
}
printf("%.1lf %.lf %.lf\n", time / n, Min_time, Maxtime);
for(int i = 0; i < k; i++)
{
if(i)
{
printf(" ");
}
printf("%d", all[i].num);
}
printf("\n");
return 0;
}
习题8.2 银行排队问题之单队列多窗口加VIP服务 (30分)
#include <bits/stdc++.h>
struct consumer
{
double arrive;
double process;
double start;
double end;
double wait;
int vip;
int skip;
}c[1001];
struct windows
{
int count;
int availiable;
double end;
}w[11];
using namespace std;
int main()
{
memset(c,0,sizeof(c));
memset(w,0,sizeof(w));
int n,k,arrive,process,vip;
cin>>n;
for (int i=0;i<n;i++)
{
cin>>arrive>>process>>vip;
if (process>60) process=60;
c[i].arrive=arrive;
c[i].process=process;
c[i].vip=vip;
}
int v;
cin>>k>>v;
for (int i=0;i<k;i++) w[i].availiable=1;
int count=0;
int m;
for (m=0;;m++)
{
if (count==n) break;
for (int i=0;i<k;i++) //窗口刷新
{
if (w[i].end==m)
{
w[i].availiable=1;
}
}
if (w[v].availiable==1) //vip窗口拉人
{
for (int i=0;c[i].arrive<=m&&i<n;i++)
{
if (c[i].skip==1) continue;
if (c[i].vip==1)
{
c[i].skip=1;
c[i].start=m;
c[i].end=c[i].start+c[i].process;
c[i].wait=c[i].start-c[i].arrive;
w[v].availiable=0;
w[v].end=m+c[i].process;
count++;
w[v].count++;
break;
}
}
}
for (int i=0;i<k;i++)
{
if (w[i].availiable==1)
{
for (int j=0;j<n&&c[j].arrive<=m;j++)
{
if (c[j].skip==1) continue;
c[j].start=m;
c[j].end=c[j].start+c[j].process;
c[j].skip=1;
c[j].wait=c[j].start-c[j].arrive;
w[i].availiable=0;
w[i].count++;
w[i].end=m+c[j].process;
count++;
break;
}
}
}
}
double sum=0;
int maxwait=-1,last=-1;
for (int i=0;i<n;i++)
{
sum+=c[i].wait;
if (c[i].wait>maxwait)
{
maxwait=c[i].wait;
}
if (c[i].end>last)
{
last=c[i].end;
}
// printf("*%.1lf %.1lf %.1lf\n",c[i].start,c[i].process,c[i].end);
}
printf("%.1lf %d %d\n",sum/n,maxwait,last);
printf("%d",w[0].count);
for (int i=1;i<k;i++)
{
printf(" %d",w[i].count);
}
return 0;
}
习题8.3 银行排队问题之单窗口“夹塞”版 (30分)
#include <iostream>
#include <map>
#include <queue>
#include <cstdio>
using namespace std;
#define MaxNameLen 3
#define MaxPeopleNum 10000
typedef struct People ElementType;
typedef int Position;
struct People {
int T;
int P;
char Name[MaxNameLen + 1];
Position Index;
} PQueue[MaxPeopleNum];
int main()
{
//freopen("E:in.txt", "r", stdin);
map<string, int> Group;
queue<ElementType> Que;
char Name[MaxNameLen + 1];
int N, M, L, i, j;
scanf("%d %d", &N, &M);
for (i = 0; i < M; i++) {
scanf("%d", &L);
for (j = 0; j < L; j++) {
scanf("%s", Name);
Group[Name] = i;
}
}
for (i = 0; i < N; i++) {
scanf("%s %d %d", &PQueue[i].Name, &PQueue[i].T, &PQueue[i].P);
if (PQueue[i].P > 60) {
PQueue[i].P = 60;
}
PQueue[i].Index = i;
Que.push(PQueue[i]);
}
int CurrentTime, SumWaitTime, WindowsTime, WaitTime;
ElementType X;
bool Visited[N] = {false};
CurrentTime = SumWaitTime = WindowsTime = WaitTime = 0;
while (!Que.empty()) {
X = Que.front();
Que.pop();
if (!Visited[X.Index]) { //如果没有被删除
Visited[X.Index] = true;
printf("%s\n", X.Name);
CurrentTime += WindowsTime; //解决掉上一个事务
if (X.T <= CurrentTime) { //如果顾客提前来到,累加等待时间
WaitTime = CurrentTime - X.T;
SumWaitTime += WaitTime;
} else {
CurrentTime = X.T; //否则更新当前时间,为顾客到达时间
}
WindowsTime = X.P; //添加当前事务
for (i = X.Index + 1; i < N; i++) {
if (!Visited[i] && Group.count(X.Name) && Group.count(PQueue[i].Name) && (Group[X.Name] == Group[PQueue[i].Name])) { //判断是否在同一个朋友圈
if (CurrentTime + WindowsTime >= PQueue[i].T) { //如果当前事务完成前,朋友已经来到,帮助朋友
SumWaitTime += (CurrentTime + WindowsTime - PQueue[i].T); //累加朋友等待时间
Visited[i] = true;
printf("%s\n", PQueue[i].Name);
WindowsTime += PQueue[i].P;
}
}
}
}
}
printf("%.1f", (double)SumWaitTime / (double)N);
//fclose(stdin);
return 0;
}
习题8.4 畅通工程之最低成本建设问题 (30分)
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
struct city
{
int x;
int y;
int money;
}a[4010];
int find_root(int root, int f[])
{
int dd = root;
while(root != f[root])
root = f[root];
while(dd != root)
{
int t = f[dd];
f[dd] = root;
dd = t;
}
return root;
}
bool cap(city a, city b)
{
return a.money < b.money;
}
int main()
{
int n, m;
while(scanf("%d%d",&n,&m)!=EOF)
{
int t = n;
n = m;
m = t;
int f[5010] = {0};
if(n == 0)
break;
for(int i = 1; i <= m; i++)
f[i] = i;
for(int i = 1; i <= n; i++)
{
scanf("%d%d%d", &a[i].x, &a[i].y, &a[i].money);
}
if(n < m-1)
printf("?\n");
else
{
int sum = 0, flag = 1;
sort(a + 1, a + 1 + n, cap);
for(int i = 1; i <= n; i++)
{
if(find_root(a[i].x, f) != find_root(a[i].y, f))
{
f[find_root(a[i].x, f)] = find_root(a[i].y, f);
sum += a[i].money;
}
}
for(int i = 1; i <= m; i++)
f[i] = find_root(i, f);
int ans = 0;
for(int i = 1; i <= m; i++)
if(i == f[i])
{
ans++;
if(ans >= 2)
{
flag = 0;
break;
}
}
if(flag)
cout<<sum<<endl;
else
cout<<"Impossible"<<endl;
}
}
return 0;
}
习题8.5 畅通工程之局部最小花费问题 (35分)
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <vector>
#include <map>
#include <queue>
#include <math.h>
#include <stack>
#include <utility>
#include <string>
#include <sstream>
#include <cstdlib>
#include <set>
#define LL long long
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxn = 10000 + 10;
int dir[4][2] = {{1,0},{0,1},{-1,0},{0,-1}};
struct Edge
{
int from;
int to;
int cost;
Edge(int x = 0,int y = 0,int w = 0)
{
from = x;
to = y;
cost = w;
}
} edge[maxn];
int par[1000];
int Find(int x)
{
if(x == par[x])
return x;
else
return par[x] = Find(par[x]);
}
bool cmp(Edge a,Edge b)
{
return a.cost < b.cost;
}
int main()
{
int m,n;
scanf("%d",&m);
n = m *(m - 1) / 2;
for(int i = 0; i <= 1000; i++)
{
par[i] = i;
}
for(int i = 0; i < n; i++)
{
int index;
scanf("%d %d %d",&edge[i].from,&edge[i].to,&edge[i].cost);
scanf("%d",&index);
if(index)
edge[i].cost = 0;
}
sort(edge,edge+n,cmp);
int sum = 0;
for(int i = 0; i < n; i++)
{
int x = Find(edge[i].from);
int y = Find(edge[i].to);
if(x != y)
{
par[x] = y;
sum+= edge[i].cost;
}
}
printf("%d\n",sum);
return 0;
}
END