軟件工程-程序設計課程設計實驗

1. 火車票座位分配

1.1【問題描述】

設計題目(6 選 4)

請實現一個鐵路購票系統的簡單座位分配算法,來處理一節車廂的座位分配。假設一節車廂有 20 排、
每一排 5 個座位。爲方便起見,我們用 1 到 100 來給所有的座位編號,第一排是 1 到 5 號,第二排是 6 到
10 號,依次類推,第 20 排是 96 到 100 號。購票時,一個人可能購一張或多張票,最多不超過 5 張。如果 這幾張票可以安排在同一排編號相鄰的座位,則應該安排在編號最小的相鄰座位。否則應該安排在編號最 小的幾個空座位中(不考慮是否相鄰)。

1.2【基本要求】

假設初始時車票全部未被購買,現在給了一些購票指令,請你處理這些指令。 輸入格式:輸入的第一行包含一個整數 n(1 ≤ n ≤ 100),表示購票指令的數量。第二行包含 n
個整數,每個整數 p 在 1 到 5 之間,表示要購買的票數,相鄰的兩個數之間使用一個空格分隔。 輸出格式:輸出 n 行,每行對應一條指令的處理結果。對於購票指令 p,輸出 p 張車票的編號,按從
小到大排序。
樣例輸入: 4
2 5 4 2
樣例輸出: 1 2
6 7 8 9 10
11 12 13 14
3 4
樣例說明:

  1. 購 2 張票,得到座位 1、2。
  2. 購 5 張票,得到座位 6 至 10。
  3. 購 4 張票,得到座位 11 至 14。
  4. 購 2 張票,得到座位 3、4。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
 

using namespace std;

int id[110];
int a[21];

int main(){
    memset(id,0,sizeof(id));
	int n;
	cin>>n;
	fill(a,a+21,0);
	while(n--){
		int x;
		cin>>x;
		bool flag1=false;
		for(int i=1;i<=20;i++){
			if(a[i]+x<=5){
				flag1=true;
				for(int j=a[i]+1;j<=a[i]+x;j++){
					int pos=5*(i-1)+j;
					cout<<pos<<" ";
					id[pos]=1;
				}
				a[i]+=x;
				break;
			}
		}
		if(flag1==false){
			int cnt=0;
			for(int i=1;i<=100;i++){
				if(id[i]==0){
					cout<<i<<" ";
					id[i]=1;
					cnt++;
				}
				if(cnt==x) break;
			}
		}
		cout<<endl;
	}
	return 0;
}

2. 平面塗色

2.1【問題描述】
在一個定義了直角座標系的紙上,畫一個(x1,y1)到(x2,y2)的矩形是指將橫座標範圍從 x1 到 x2,縱 座標範圍從 y1 到 y2 之間的區域塗上顏色。下圖給出了一個畫了兩個矩形的例子。第一個矩形是(1,1) 到

(4, 4),用綠色和紫色表示。第二個矩形是(2, 3)到(6, 5),用藍色和紫色表示。圖中,一共有 15 個單 位的面積被塗上顏色,其中紫色部分被塗了兩次,但在計算面積時只計算一次。在實際的塗色過程中,所 有的矩形都塗成統一的顏色,圖中顯示不同顏色僅爲說明方便。

2.2【基本要求】 給出所有要畫的矩形,請問總共有多少個單位的面積被塗上顏色。 輸入格式: 輸入的第一行包含一個整數 n(1<=n<=100),表示要畫
的矩形的個數。接下來 n 行,每行 4 個非負整數,分別表示要畫的矩形的 左下角的橫座標與縱座標,以及右上角的橫座標與縱座標(0<=橫座標、 縱座標<=100)。
輸出格式:輸出一個整數,表示有多少個單位的面積被塗上顏色。 樣例輸入:
2
1 1 4 4
2 3 6 5
樣例輸出 15
在這裏插入圖片描述

#include<cstring>
#include<iostream>

using namespace std;

const int MAXN = 100 + 5; 
bool p[MAXN][MAXN];//建立平面圖

int main() 
{
    int n, x1, y1, x2, y2, ans = 0;
    cin >> n;
    memset(p, false, sizeof(p));
    while (n--) //讀入圖型多個,重疊部分都設置爲true
        {
        cin >> x1 >> y1 >> x2 >> y2;
        for (int i = x1; i < x2; i++)
            for (int j = y1; j < y2; j++)
                p[i][j] = true;
    }
    //計數
    for (int i = 0; i < MAXN; i++) 
        for (int j = 0; j < MAXN; j++) 
            if (p[i][j]) 
                ans++;
    cout << ans << endl;
    return 0;
}

3. 文本文件單詞統計

3.1【問題描述】
假設有如下的英文文本文檔:(文件名是:History.txt)

History
Taiyuan University of Technology (TYUT) can trace its origin to the Western Learning School, Shanxi Grand Academy, established in 1902 as one of the earliest three universities in China’s higher education history. Having developed through many different stages, TYUT has successively used many names: Engineering Department of Shanxi Grand University; School of Engineering, Shanxi University; becoming independent in 1953, Taiyuan Institute of Technology was under direct administration of Ministry of Higher Eeducation; handed back to Shanxi Province in 1962; Taiyuan University of Technology in 1984; merging Shanxi Institute of Mining in 1997, which was founded in 1958 by Ministry of Coal, then new Taiyuan University of Technology; included in “211” Project the same year, a national higher education promotion program for the 21st century.
設計 C 或 C++程序,統計在這樣的英文文本文件中,出現了多少個單詞(不區分大小寫),每個單詞
出現了幾次。連續的英文字符都認爲是單詞(不包括數字),單詞之間用空格或標點符號分隔。

3.2【基本要求】

要統計英文文本文件中出現了哪些單詞,就要從文件中讀取字符,讀取出來的連續英文字符認爲是一 個單詞,遇空格或標點符號單詞結束。
使用線性表記錄單詞以及每個單詞出現的次數。線性表中的單詞按字典順序存儲。 線性表的順序存儲結構如下:(必須使用如下定義的存儲結構,否則無效)
#define LIST_INIT_SIZE 100 //順序表存儲空間的初始分配量
#define LISTINCREMENT 10 //順序表存儲空間的分配增量 typedef struct{
char word[21] //存儲單詞,不超過 20 個字符
int count; //單詞出現的次數
} ElemType; //順序表元素類型 typedef struct{
ElemType *elem; //存儲空間基址
int length; //當前長度
int listsize; //當前分配的存儲容量
} SqList; //順序表類型

3.3【功能設計】

3.3.1 實現順序表的基本操作(必須使用下面給定的函數名和參數表,否則無效)

⑴順序表的初始化:InitList(SqList &L)
⑵順序表上查找指定的單詞:LocateElem(SqList &L,char *s) 若找到,單詞的出現次數增 1,返回 0,否則返回該單詞在順序表中的插入位置。
⑶在順序表上插入新的單詞:InsertList(SqList &L,int i,char *s) 要求按字典順序有序。新單詞的出現次數爲 1.
⑷輸出順序表上存儲的單詞統計信息:PrintList(SqList &L) 輸出文件中每個單詞出現的次數以及文件中總的單詞數(可輸出到文件中)。

3.3.2 統計單詞數

統計過程如下:
(1)輸入要統計單詞的文本文件名,打開相應的文件;
(2)初始化順序表;
(3)從文本文件中讀取字符,直到文件結束。具體描述如下:
while (讀文件沒有結束)
{
過濾單詞前的非字母字符;

讀取一個單詞,以字符串形式存儲在一個字符數組中; 在線性表中查找該單詞,若找到,單詞的出現次數加 1,否則返回其插入位置; 上一步中,若沒找到,則進行插入操作;
處理下一個單詞。
}
(4)關閉文件,輸出統計結果。

3.4【測試數據】
將上述給定的英文文檔寫入文本文件:History.txt 作爲測試數據文件。

#include <cstdio>
#include <cstring>
#include <cstdlib>
#define LIST_INIT_SIZE 100
#define LISTINCREMENT 10

typedef struct
{
    char word[21];
    int count;
} ElemType;
typedef struct
{
    ElemType *elem;
    int length;
    int listsize;
} SqList;

int InitList(SqList *p)
{
    p->elem=(ElemType*)malloc(LIST_INIT_SIZE*sizeof(ElemType));
    if(p->elem==NULL)
        return 0;
    p->length=0;

    p->listsize=LIST_INIT_SIZE;
    return 1;
}

int LocateElem(SqList *p,char *word)
{
    int low,high,mid;
    low=0;
    high=p->length-1;
    while(low<=high)
    {
        mid=(low+high)/2;
        if(strcmp(word,p->elem[mid].word)==0)	//表中進行二分查找
        {
            p->elem[mid].count++;
            return 0;
        }
        else if(strcmp(word,p->elem[mid].word)<0)
            high=mid-1;
        else
            low=mid+1;
    }
    return low+1;	//返回插入點序號
}

int InsertList(SqList *p,int i,char *word)
{
    int j;
    ElemType *base;
    if(p->length>=p->listsize)
    {
        base=(ElemType*)realloc(p->elem,(p->listsize+LISTINCREMENT)*sizeof(ElemType));
        if(base==NULL)
            return 0;
        p->listsize=p->listsize+LISTINCREMENT;	//擴充表長
        p->elem=base;
    }
    for(j=p->length; j>=i; j--)
        p->elem[j]=p->elem[j-1];
    strcpy(p->elem[i-1].word,word);
    p->elem[i-1].count=1;
    p->length++;
    return 1;
}

void PrintList(SqList *p,int num)

{
    FILE *fw;
    int i;
    int no=num;
    fw=fopen("E:\\History.txt","w");
    fprintf(fw,"  文 章 共 有 %d   個 單 詞 \n   以 下 按 字 典 順 序 排 序 顯 示 出 現 次   數\n******************************************\n",no);
    fprintf(fw,"單詞	出現次數\n",no);
    for(i=0;i<p->length;i++)
    fprintf(fw,"%-24s %-5d\n",p->elem[i].word,p->elem[i].count);
    fprintf(fw,"******************************************\n");
    fclose(fw);
}

//主函數
int main()
{
    SqList L;
    char word[21],ch,filename[30],filename1[50];
    int num=0,i,j=0,mark=0;
    FILE *fp;
    InitList(&L);
    printf("請輸入文件名:\n");
    scanf("%s",&filename);
    sprintf(filename1,"E:\\%s.txt",filename);
    getchar();
    if((fp=fopen(filename1,"r"))==NULL)
    {
        printf("打開文件失敗!\n");
        getchar();
        exit(0);
    }
    ch=fgetc(fp);
    while(ch!=EOF)
    {

        if((ch>='A'&&ch<='Z')||(ch>='a'&&ch<='z'))
        {
            ch=ch>='A'&&ch<='Z'?ch+32:ch;
            word[j++]=ch;
            mark=1;
        }
        else
        {

            if (mark==1)
            {
                if (j>20)
                {
                    printf("太長不統計");
                }
                num++;
                word[j]='\0';
                mark=0;
                j=0;
                i=LocateElem(&L,word);
                if(i>0)
                    InsertList(&L,i,word);
            }
        }

        ch=fgetc(fp);

    }
    fclose(fp);
    printf("完成。");
    PrintList(&L,num);
    getchar();
}

在這裏插入圖片描述

4. 分數的加減乘除

4.1【問題描述】 用分數形式表示的有理數類如下(C++語言描述):

//(C++語言描述): 
class Rational{
private:
int x,y;	//成員變量 x 和 y,分別存放分子和分母 public:
Rational(int a=1,int b=1);	//具有默認參數的構造函數,默認值爲 1
Rational Add(Rational &r);	//求兩個分數的和 
Rational Sub(Rational &r);	//求兩個分數的差 
Rational Mul(Rational &r);	//求兩個分數的積 
Rational Div(Rational &r);	//求兩個分數的商
Rational operator+(Rational &r); //重載“+”運算符,求兩個分數的和 
Rational operator-(Rational &r); //重載“-”運算符,求兩個分數的差 
Rational operator*(Rational &r); //重載“*”運算符,求兩個分數的積 
Rational operator/(Rational &r);  //重載“/”運算符,求兩個分數的商 
int Divisor(int a,int b);	//求最大公約數
friend ostream& operator<<(ostream &output,Rational &r);       //以 x/y 的形式輸出分數
};

4.2【基本要求】
1.成員變量 x 和 y,分別存放分子和分母, 要求分數以最簡形式存放。例如:分數 2/4 應簡化爲 1/2。
2.定義成員函數 Add、Sub、Mul 和 Div,求兩個分數的和差積商。計算結果仍以最簡形式存放。
3.重載運算符“+、-、*、/”,求兩個分數的和差積商。計算結果仍以最簡形式存放。
4.定義友元函數,重載“<<”運算符,以 x/y 的形式輸出分數。例如,有如下的主函數:

int main(){
Rational a(5,15),b(1,-2),c; 
cout<<"a="<<a<<endl;
cout<<"b="<<b<<endl; 
c=a.Add(b);	//c=a+b; 
cout<<"a+b="<<c<<endl; 
c=a.Sub(b);	//c=a-b; 
cout<<"a-b="<<c<<endl; 
c=a.Mul(b);	//c=a*b; 
cout<<"a*b="<<c<<endl; 
c=a.Div(b);	//c=a/b; 
cout<<"a/b="<<c<<endl;
}

運行結果如圖 4-1 所示:
在這裏插入圖片描述

5. 交通諮詢系統(最短路徑問題)

5.1【問題描述】

在交通網絡非常發達、交通工具和交通方式不斷更新的今天,人們在出差、旅遊或做其他出行時,不 僅關心節省交通費用,而且對里程和所需要的時間等問題也感興趣。對於這樣一個人們關心的問題,可用 一個圖結構來表示交通網絡系統,利用計算機建立一個交通諮詢系統。圖中的頂點表示城市,邊表示城市 之間的交通關係。這個交通系統可以回答出行旅客提出的各種路徑選擇問題。例如,問題之一:“一位旅 客要從 A 城到 B 城,他希望選擇一條途中中轉次數最少的路線。”假設圖中每一站都需要換車,那麼這個 問題反映到圖上就是要找一條從頂點 A 到頂點 B 的所含邊數目最少的路徑。我們只需要從頂點 A 出發對圖 作廣度優先搜索,一旦遇到頂點 B 就終止。由此所得廣度優先生成樹上,從根頂點 A 到頂點 B 的路徑就是 中轉次數最少的路徑。路徑上 A 與 B 之間的頂點就是路徑的中轉站,但這只是一類最簡單的圖的最短路徑 問題。系統還可以回答諸如此類的等等的路徑選擇問題。
設計一個交通諮詢系統,爲出差、旅遊或做其他出行的客人提供各種路徑選擇信息查詢服務。

5.2【基本要求】

設計一個交通諮詢系統,能讓旅客諮詢從任一個城市頂點到另一城市頂點之間的最短路徑(里程)或 最低花費或最少時間等問題。對於不同的諮詢要求,可輸入城市間的路程或所需時間或所需費用。
本設計共分三部分,一是建立交通網絡圖的存儲結構;二是解決單源最短路徑問題;三是實現任兩個 城市頂點之間的最短路徑問題。

5.2.1 建立圖的存儲結構

圖的鄰接矩陣表示,除了需用一個二維數組存儲頂點之間的相鄰關係的鄰接矩陣外,通常還需要使用 一個具有 n 個元素的一維數組來存儲頂點信息,其中下標爲 i 的元素存儲頂點 i 的信息。因此,圖的鄰接

矩陣的存儲結構定義如下:

#define MVNum 50	//最大頂點數 
typedef struct{
VertexType vexs[MVNum];	//頂點數組,類型假定爲 char 型 
Adjmatrix arcs[MVNum][MVNum];	//鄰接矩陣,假定爲 int 型
} MGraph;	//圖的鄰接矩陣存儲類型

5.2.2 單源最短路徑

爲了敘述方便,我們把路徑上的開始點稱爲源點,路徑的最後一個頂點爲終點。 那麼,如何求得給定有向圖的單源最短路徑呢?迪傑斯特拉(Dijkstra)提出按路徑長度遞增產生諸
點的最短路徑算法,稱之爲迪傑斯特拉算法。

5.2.3 任意一對頂點間最短路徑

任意一對頂點間最短路徑問題,是對於給定的有向網絡圖 G=(V,E),要對 G 中任意一對頂點有序對 “v,w(v !=w)”,找出 v 到 w 的最短路徑。
要解決這個問題,我們可以依次把有向網絡圖中每個頂點作爲源點,重複執行前面討論的迪傑斯特拉
算法 n 次,即可以求得每對頂點之間的最短路徑。這裏還可以用另外一種方法,稱作費洛伊德(Floyd) 算法。

5.3【測試實例】

5.3.1 測試實例一

圖 5-1 是一個有向圖,求頂點 a 到其餘頂點的最短路徑。
在這裏插入圖片描述

來表示的,頂點的字母就用其對應的序號來表示,如 a 用 1
來代替,„„。

3.4.2 運行實例二

圖 5-2 是一個簡單的交通網絡圖。求頂點“北京”到其餘各城市之間的最短路徑;並分別求“成都” 到“上海”之間以及“上海”到“西安”之間的最短路徑。
爲了操作方便,對於圖的頂點可以用序號來表示的,頂點的字母就用其對應的序號來表示,如北京用
1 來代替,„„。
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章