Week2 作業&實驗

作業題部分

A - Maze

東東有一張地圖,想通過地圖找到妹紙。地圖顯示,0表示可以走,1表示不可以走,左上角是入口,右下角是妹紙,這兩個位置保證爲0。既然已經知道了地圖,那麼東東找到妹紙就不難了,請你編一個程序,寫出東東找到妹紙的最短路線。
Input
  輸入是一個5 × 5的二維數組,僅由0、1兩數字組成,表示法陣地圖。
Output
  輸出若干行,表示從左上角到右下角的最短路徑依次經過的座標,格式如樣例所示。數據保證有唯一解。
Sample Input
0 1 0 0 0
0 1 0 1 0
0 1 0 1 0
0 0 0 1 0
0 1 0 1 0
Sample Output
(0, 0)
(1, 0)
(2, 0)
(3, 0)
(3, 1)
(3, 2)
(2, 2)
(1, 2)
(0, 2)
(0, 3)
(0, 4)
(1, 4)
(2, 4)
(3, 4)
(4, 4)
Hint
座標(x, y)表示第x行第y列,行、列的編號從0開始,且以左上角爲原點。
另外注意,輸出中分隔座標的逗號後面應當有一個空格。

解析:

本題爲經典的迷宮的問題,尋找從左上角到右下角的路徑。總體的思路是通過BFS的方法來求路徑。BFS的方法則是採用隊列,通過兩個偏移量數組實現上下左右。而路徑,則是由最初聲明的point類的一個二維數組path保存。Path[x][y](point類型)裏存的是它的前一個點的座標,這樣就可以依次找到它的路徑。輸出時,從終點(4,4)開始,將到達的點入棧,然後將這個點對應的path[][](即它的前一個點)入棧,循環這個過程,到(0,0)爲止,即可將完整路徑倒序入棧。輸出即可。

源碼:

#include<iostream>
#include<queue>
#include<stack>
using namespace std;
// 基本操作 
struct point
{
    int x;
	int y;
    point(int x, int y) : x(x), y(y){}
    point(){}
}path[10][10];

bool vis[10][10];
int a[10][10], dis[10][10];
int sx, sy, tx, ty;
queue<point> Q;
stack<point> s;
int dy[] = {-1, 1, 0, 0};
int dx[] = {0, 0, -1, 1};


// BFS,通過隊列和偏移量數組實現 
int bfs()
{
    Q.push(point(sx, sy));
    vis[sx][sy] = true;
    dis[sx][sy] = 0;
    while(!Q.empty())
    {
        point now = Q.front();
		Q.pop();
        // 上下左右尋找可到達的點 
		for(int i = 0 ; i < 4 ; ++i)
        {
            int x = now.x + dx[i], y = now.y + dy[i];
            if(x >= 0 && x < 5 && y >= 0 && y < 5 && vis[x][y] == 0 && a[x][y] == 0)
            {
                dis[x][y] = dis[now.x][now.y] + 1;
				vis[x][y] = 1;
                Q.push(point(x, y));
                // 用path[][]記錄前一個點座標 
                path[x][y] = point(now.x, now.y);
            }
        }
    }
    return 0;
}
int main()
{
    for(int i = 0 ; i < 5 ; i++)
		for(int j = 0 ; j < 5 ; j++)
			vis[i][j] = 0;
	for(int i = 0 ; i < 5 ; i++)
        for(int j = 0 ; j < 5 ; j++)
            cin >> a[i][j];
    bfs();
    
    // 入棧,尋找路徑 
    int px = 4, py = 4;
    while(true)
    {
        s.push(point(px, py));
    	
		int b = px, c = py; 
		px = path[b][c].x;
        py = path[b][c].y;
        if(px == 0 && py == 0) 
			break;
    }
    
    // 輸出路徑
	cout << "(0, 0)" << endl; 
	point step;
	while(!s.empty())
    {
        step = s.top(); 
		s.pop();
        cout << "(" << step.x << ", " << step.y << ")" << endl;
    }
    return 0;
}

B - Pour Water

倒水問題 “fill A” 表示倒滿A杯,"empty A"表示倒空A杯,“pour A B” 表示把A的水倒到B杯並且把B杯倒滿或A倒空。
Input
輸入包含多組數據。每組數據輸入 A, B, C 數據範圍 0 < A <= B 、C <= B <=1000 、A和B互質。
Output
你的程序的輸出將由一系列的指令組成。這些輸出行將導致任何一個罐子正好包含C單位的水。每組數據的最後一行輸出應該是“success”。輸出行從第1列開始,不應該有空行或任何尾隨空格。
Sample Input
2 7 5
2 7 4
Sample Output
fill B
pour B A
success
fill A
pour A B
fill A
pour A B
success
Notes
如果你的輸出與Sample Output不同,那沒關係。對於某個"A B C"本題的答案是多解的,不能通過標準的文本對比來判定你程序的正確與否。 所以本題由 SPJ(Special Judge)程序來判定你寫的代碼是否正確。

解析:

這是一個隱式圖問題。類似於迷宮問題,以最終水量4爲例,這道題等價於從(0,0)的初始狀態到終點(4,n)或者(m,4)的迷宮。因此我們用BFS的做法來實現。爲了便於輸出,我們在結構體status中加入一個字符串變量string s,用來存放“fill A”、“pour A B”等句子。

源碼:

#include<queue>
#include<iostream>
#include<string>
#define maxn 1000
using namespace std;

int vis[maxn][maxn];

// 隱式圖的節點 
struct status
{
    int a;  // A杯水量 
	int b;  // B杯水量 
	int step;  // 步數 
    string s[maxn];  // 操作名 
}form;

// BFS 
int bfs(int A, int B, int C)
{
    status node;
    // 初始化(0,0),也是最初的狀態 
	node.a = 0;
	node.b = 0;
	node.step = 0;
	
    queue<status> q;
    q.push(node);
    
	while(!q.empty())
    {
        // 取隊首元素top
		status t = q.front();
        q.pop();
        
        // 結束的標誌 
        if(t.a == C || t.b == C)
        {
            form = t;
            return 1;
        }
        // vis[A][t.b]代表b杯不動,a杯加滿 
        // 當vis[A][t.b]爲0時,代表這個點未到達過,執行下面操作 
		if(!vis[A][t.b])
        {
			status p;
			p = t;
            p.a = A;   // 將A加滿
			vis[p.a][p.b] = 1; // 標記已到達 
			p.step++;  // 步數加一 
            p.s[p.step] = "fill A"; // 記錄操作名 
            q.push(p); // 入隊 
        }
        
        //下面的幾種情況類似,不再詳細註釋 
        
        // vis[t.a][B]代表a杯不動,b杯加滿 
        if(!vis[t.a][B])
        {
            status p;
			p = t;
            p.b = B;
			vis[p.a][p.b] = 1;
			p.step++;
            p.s[p.step] = "fill B";  
            q.push(p);
        }
        // vis[0][t.b]代表b杯不動,a杯倒空 
        if(!vis[0][t.b])
        {
            status p;
			p = t;
            p.a = 0;
            vis[p.a][p.b] = 1;
            p.step++;
            p.s[p.step] = "empty A";
            q.push(p);
        }
        // vis[t.a][B]代表a杯不動,b杯倒空 
        if(!vis[t.a][0])
        {
            status p;
			p = t;
            p.b = 0;
            vis[p.a][p.b] = 1;
            p.step++;
            p.s[p.step] = "empty B";
            q.push(p);
        }
        // A中水全倒入B中,如果A中剩餘的水不足以使B滿,則A變爲0,B變爲a + b
		// 如果能使B滿還有溢出,則B滿,A爲a + b - B 
        if(!vis[(B - t.b >= t.a) ? 0 : t.a - B + t.b][(B - t.b >= t.a) ? t.a + t.b : B])
        {
            status p;
			p = t;
            p.a = (B - t.b >= t.a) ? 0 : t.a - B + t.b;
            p.b = (B - t.b >= t.a) ? t.a + t.b : B;
            vis[p.a][p.b] = 1;
            p.step++;
            p.s[p.step] = "pour A B";
            q.push(p);
        }
        // B中水全倒入A中,如果B中剩餘的水不足以使A滿,則B變爲0,A變爲a + b
		// 如果能使A滿還有溢出,則A滿,B爲a + b - A 
		if(!vis[(A - t.a >= t.b) ? t.a + t.b : A][(A - t.a >= t.b) ? 0 : t.b - A + t.a])
        {
            status p;
			p = t;
            p.a = (A - t.a >= t.b) ? t.a + t.b : A;
            p.b = (A - t.a >= t.b) ? 0 : t.b - A + t.a;
            vis[p.a][p.b] = 1;
            p.step++;
            p.s[p.step] = "pour B A";
            q.push(p);
        }
    }
    return 0;2 
}

int main()
{
    int A, B, C;
	
    while(cin >> A >> B >> C)
    {
    	int m = max(A, B);
		for(int i = 0 ; i < m ; i++)
    		for(int j = 0 ; j < m ; j++)
    			vis[i][j] = 0;
		bfs(A, B, C);
		// 輸出s[],即爲操作名。注意這個解不是唯一的。 
        for(int i = 1 ; i <= form.step ; i++)
            cout << form.s[i] << endl;
        cout << "success" << endl;
	}
}

回顧:

在VJ上測試這道題時,剛開始發生了CE的錯誤。後經分析發現,代碼裏沒有引用頭文件導致cout無法直接輸出string類型。仔細瞭解後發現不同編譯器對cout的輸出不一樣,C++的編譯器沒有時無法cout string類型,而G++則可以。

實驗部分

A - 化學 (編譯器選 GNU G++)

化學很神奇,以下是烷烴基。
在這裏插入圖片描述
假設如上圖,這個烷烴基有6個原子和5個化學鍵,6個原子分別標號1~6,然後用一對數字 a,b 表示原子a和原子b間有一個化學鍵。這樣通過5行a,b可以描述一個烷烴基
你的任務是甄別烷烴基的類別。
原子沒有編號方法,比如
1 2
2 3
3 4
4 5
5 6

1 3
2 3
2 4
4 5
5 6
是同一種,本質上就是一條鏈,編號其實是沒有關係的,可以在紙上畫畫就懂了
Input
輸入第一行爲數據的組數T(1≤T≤200000)。每組數據有5行,每行是兩個整數a, b(1≤a,b≤6,a ≤b)
數據保證,輸入的烷烴基是以上5種之一
Output
每組數據,輸出一行,代表烷烴基的英文名
Example
Input
2
1 2
2 3
3 4
4 5
5 6
1 4
2 3
3 4
4 5
5 6
Output
n-hexane
3-methylpentane

解析:

仔細觀察圖發現,以樹的角度看待圖中的五種烷烴基:
(1) n-hexane有兩個葉子節點;
(2)2,3-dimethylbutane和2,2-dimethylbutane都有4個葉子節點,可是2,2-dimethylbutane中有一個節點度爲4(即與其它4個點連接)而2,3沒有這種節點。
(3)3-methylpentane與2-methylpentane,度爲3的點連接的葉子數分別爲1和2。
這樣我們就確定了5種不同的烷烴基。我們可以通過記錄葉節點數n、度爲4的節點數r以及關注度爲3的點所連接的葉子數即可區分五種烷烴基。
建立一個數組c[7]用來儲存每個節點的度。

源碼:

#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;

struct graph
{
	int a[5];
	int b[5];
};
 
int creatg(graph gra){
	// c[7]數組用於儲存每個點的度 ,c[0]不用 
	int c[7] = {0,0,0,0,0,0,0};
	for(int i = 0 ; i < 5 ; i++){
		if(gra.a[i] == 1 || gra.b[i] == 1)
			c[1]++;
		if(gra.a[i] == 2 || gra.b[i] == 2)
			c[2]++;
		if(gra.a[i] == 3 || gra.b[i] == 3)
			c[3]++;
		if(gra.a[i] == 4 || gra.b[i] == 4)
			c[4]++;
		if(gra.a[i] == 5 || gra.b[i] == 5)
			c[5]++;
		if(gra.a[i] == 6 || gra.b[i] == 6)
			c[6]++;
	}
	
	// 統計葉節點數n、度爲4的節點數r,記錄度爲3的節點p 
	int n = 0, r = 0, p = 0;
	for(int i = 1 ; i < 7 ; i++){
		if(c[i] == 1)
			n++;
		if(c[i] == 4)
			r++;
		if(c[i] == 3)
			p = i;
	}
	// 先找出3種	
	if(n == 2)
		cout << "n-hexane" << endl;
	if(n == 4 && r == 0)
		cout << "2,3-dimethylbutane" << endl;
	if(n == 4 && r == 1)
		cout << "2,2-dimethylbutane" << endl;
	//  區分另外兩種 
	if(n == 3)
	{
		// 用d[3]來記錄度爲3的節點的三個鄰接節點 
		int d[3]; 
		int tag = 0;
		for(int i = 0 ; i < 5 ; i++){
			if(gra.a[i] == p)
			{
				d[tag] = gra.b[i];
				tag++;
			}	
			if(gra.b[i] == p)
			{
				d[tag] = gra.a[i];
				tag++;
			}
		};
		
		int u = 0; // u代表鄰接節點中葉子的數目 
		
		for(int i = 0 ; i < 3 ; i++)
		{
			// 鄰接節點是葉子: 
			if(c[d[i]] == 1)
				u++;	
		}
		// 區分剩下兩個 
		if(u == 1)
			cout << "3-methylpentane" << endl;
		else
			cout << "2-methylpentane" << endl;
	}
	
		
}

int main(){
	graph gra;
	int n;
	cin >> n;
	for(int j = 0 ; j < n ; j++)
	{
		for(int i = 0 ; i < 5 ; i++)
		{
			cin >> gra.a[i] >> gra.b[i];
		}
		creatg(gra);
	}
	
}

B - 爆零(×)大力出奇跡(√)

程序設計思維作業和實驗使用的實時評測系統,具有及時獲得成績排名的特點,那它的功能是怎麼實現的呢?
我們千辛萬苦懟完了不忍直視的程序並提交以後,評測系統要麼返回AC,要麼是返回各種其他的錯誤,不論是怎樣的錯法,它總會給你記上一筆,表明你曾經在這兒被坑過,而當你歷經千辛終將它AC之後,它便會和你算筆總賬,表明這題共錯誤提交了幾次。
在歲月的長河中,你通過的題數雖然越來越多,但通過每題時你所共花去的時間(從最開始算起,直至通過題目時的這段時間)都會被記錄下來,作爲你曾經奮鬥的痕跡。特別的,對於你通過的題目,你曾經的關於這題的每次錯誤提交都會被算上一定的單位時間罰時,這樣一來,你在做出的題數上,可能領先別人很多,但是在做出同樣題數的人中,你可能會因爲罰時過高而處於排名上的劣勢。
例如某次考試一共八道題(A,B,C,D,E,F,G,H),每個人做的題都在對應的題號下有個數量標記,負數表示該學生在該題上有過的錯誤提交次數但到現在還沒有AC,正數表示AC所耗的時間,如果正數a跟上了一對括號,裏面有個正數b,則表示該學生AC了這道題,耗去了時間a,同時曾經錯誤提交了b次。例子可見下方的樣例輸入與輸出部分。
Input
輸入數據包含多行,第一行是共有的題數n(1≤n≤12)以及單位罰時m(10≤m≤20),之後的每行數據描述一個學生的信息,首先是學生的用戶名(不多於10個字符的字串)其次是所有n道題的得分現狀,其描述採用問題描述中的數量標記的格式,見上面的表格。
Output
根據這些學生的得分現狀,輸出一個實時排名。實時排名顯然先按AC題數的多少排,多的在前,再按時間分的多少排,少的在前,如果湊巧前兩者都相等,則按名字的字典序排,小的在前。每個學生佔一行,輸出名字(10個字符寬),做出的題數(2個字符寬,右對齊)和時間分(4個字符寬,右對齊)。名字、題數和時間分相互之間有一個空格。數據保證可按要求的輸出格式進行輸出。
Sample Input
8 20
GuGuDong 96 -3 40(3) 0 0 1 -8 0
hrz 107 67 -3 0 0 82 0 0
TT 120(3) 30 10(1) -3 0 47 21(2) -2
OMRailgun 0 -99 -8 0 -666 -10086 0 -9999996
yjq -2 37(2) 13 -1 0 113(2) 79(1) -1
Zjm 0 0 57(5) 0 0 99(3) -7 0
Sample Output
TT 5 348
yjq 4 342
GuGuDong 3 197
hrz 3 256
Zjm 2 316
OMRailgun 0 0

解析:

這個題類似第一週的長方形排序題,是一種多條件的排序。其優先級依次爲:
(1)做出來的題目 降序
(2)花費時間(含罰時) 升序
(3)名字的字典序 升序
通過排序函數compare來實現排序。

源碼:

#include<iostream>
#include<cstring>
using namespace std;

struct student
{
    char name[10];  // ID 
    int solved;     // A掉的題數 
    int timescore;  // 耗時 
}stu[1000];

// 用於排序的比較函數 
int cmp(int j, int i)
{
    // 第一優先級,解決問題數 
	if(stu[j].solved < stu[i].solved)
    	return 1;
    else 
        if(stu[j].solved == stu[i].solved)
        	// 第二優先級,耗時 
			if(stu[j].timescore > stu[i].timescore)
        		return 1;
        	else
				if(stu[j].timescore == stu[i].timescore)
            		// 第三優先級,姓名字典序 
					if(strcmp(stu[j].name, stu[i].name) > 0)
        				return 1; 
    return 0;
}

// 計算乘以10的n次方的函數,便於將字符串保存的數轉化爲int 
int e10(int n){
	int a = 1;
	for(int i = 0 ; i < n ; i++)
	{
		a *= 10;
	}
	return a;
}

int main()
{
	int n, m;
	cin >> n >> m;
	int i = 1;
	while(cin >> stu[i].name)
	{
        char a[100]; // 用字符串保存 
        stu[i].solved = 0; 
        stu[i].timescore = 0;
        // 循環求n道題的結果 
		for(int j = 1 ; j <= n ; j++)
        {
            cin >> a;
            if(a[0] != '-' && a[0] > '0')
            {
                // 問題解決 
				int tag = 0; 
                int flags = 0;
                stu[i].solved ++;
                
                // 求輸入的第一個數據的長度length 
                int length = strlen(a);
                // 利用length求第一個數據 ,倒序處理 
				for(int j = length - 1 ; j >= 0 ; j--)
                {
                    // 數據部分轉化 
					if(a[j] != ')' && a[j] != '(')
                    {
						// 計算時間 
						int times = a[j] - '0';
                        stu[i].timescore += times * e10(tag);
						// 如果flag是true,則說明這個數據是未通過次數,應該*20記罰時,由於前面已經加了1,只需再乘(m-1) 
						if(flags)
                        	stu[i].timescore += times * e10(tag) * (m - 1);
                        tag++;	
                	}
					// 如果存在後括號,代表下次處理的數字是未通過的次數,flag變爲1 
					if(a[j] == ')')
                    {
                        flags = 1;
                        tag = 0;
                	} 
					// flag變0,代表下一個數據是正常時間 
					if(a[j] == '(')
                    {
                        flags = 0;
                        tag = 0;
                	} 
            	}
        	}
    	}
    	// 插入排序,找到適合輸入數據的位置插入 
    	if(i >= 2)
    	{
			for(int j = i - 1 ; j > 0 ; j--)
    		{
            	if(cmp(j, i) && !cmp(j - 1 , i))
            	{
					student tmp = stu[i];
            		for(int k = i - 1 ; k >= j ; k--)
                		stu[k + 1] = stu[k];
            		stu[j] = tmp;
            		break;
            	}
        	} 
     	}
     	i++;
	}
	// 格式化輸出 
	for(int j = 1 ; j < i ; j++)
	{
		printf("%-10s ", stu[j].name);
		printf("%2d ", stu[j].solved);
		printf("%4d\n", stu[j].timescore);
	}  
}

C - 瑞神打牌 (不支持C++11,G++和C++編譯器都試試提交哈)

瑞神HRZ因爲疫情在家閒得無聊,同時他又非常厲害,所有的課對他來說都是水一水就能拿A+,所以他無聊,找來了另外三個人:咕咕東,騰神以及zjm來打牌(天下苦瑞神久矣)。
顯然,牌局由四個人構成,圍成一圈。我們稱四個方向爲北 東 南 西。對應的英文是North,East,South,West。遊戲一共由一副撲克,也就是52張構成。開始,我們指定一位發牌員(東南西北中的一個,用英文首字母標識)開始發牌,發牌順序爲順時針,發牌員第一個不發自己,而是發他的下一個人(順時針的下一個人)。這樣,每個人都會拿到13張牌。
現在我們定義牌的順序,首先,花色是(梅花)<(方片)<(黑桃)<(紅桃),(輸入時,我們用C,D,S,H分別表示梅花,方片,黑桃,紅桃,即其單詞首字母)。對於牌面的值,我們規定2 < 3 < 4 < 5 < 6 < 7 < 8 < 9 < T < J < Q < K < A。
現在你作爲上帝,你要從小到大排序每個人手中的牌,並按照給定格式輸出。(具體格式見輸出描述和樣例輸出)。
Input
輸入包含多組數據
每組數據的第一行包含一個大寫字符,表示發牌員是誰。如果該字符爲‘#’則表示輸入結束。
接下來有兩行,每行有52個字符,表示了26張牌,兩行加起來一共52張牌。每張牌都由兩個字符組成,第一個字符表示花色,第二個字符表示數值。
Output
輸出多組數據發牌的結果,每組數據之後需要額外多輸出一個空行!!!!!
每組數據應該由24行的組成,輸出按照順時針方向,始終先輸出South Player的結果,每位玩家先輸出一行即玩家名稱(東南西北),接下來五行,第一行和第五行輸出固定格式(見樣例),第二行和第四行按順序和格式輸出數值(見樣例),第三行按順序和格式輸出花色(見樣例)。
Sample Input
N
CTCAH8CJD4C6D9SQC7S5HAD2HJH9CKD3H6D6D7H3HQH4C5DKHKS9
SJDTS3S7S4C4CQHTSAH2D8DJSTSKS2H5D5DQDAH7C9S8C8S6C2C3

Sample Output
South player:
±–±--±–±--±–±--±–±--±–±--±–±--±–+
|6 6|A A|6 6|J J|5 5|6 6|7 7|9 9|4 4|5 5|7 7|9 9|T T|
| C | C | D | D | S | S | S | S | H | H | H | H | H |
|6 6|A A|6 6|J J|5 5|6 6|7 7|9 9|4 4|5 5|7 7|9 9|T T|
±–±--±–±--±–±--±–±--±–±--±–±--±–+
West player:
±–±--±–±--±–±--±–±--±–±--±–±--±–+
|2 2|5 5|9 9|K K|5 5|7 7|9 9|4 4|T T|J J|A A|8 8|A A|
| C | C | C | C | D | D | D | S | S | S | S | H | H |
|2 2|5 5|9 9|K K|5 5|7 7|9 9|4 4|T T|J J|A A|8 8|A A|
±–±--±–±--±–±--±–±--±–±--±–±--±–+
North player:
±–±--±–±--±–±--±–±--±–±--±–±--±–+
|3 3|4 4|J J|2 2|3 3|T T|Q Q|K K|8 8|Q Q|K K|2 2|3 3|
| C | C | C | D | D | D | D | D | S | S | S | H | H |
|3 3|4 4|J J|2 2|3 3|T T|Q Q|K K|8 8|Q Q|K K|2 2|3 3|
±–±--±–±--±–±--±–±--±–±--±–±--±–+
East player:
±–±--±–±--±–±--±–±--±–±--±–±--±–+
|7 7|8 8|T T|Q Q|4 4|8 8|A A|2 2|3 3|6 6|J J|Q Q|K K|
| C | C | C | C | D | D | D | S | S | H | H | H | H |
|7 7|8 8|T T|Q Q|4 4|8 8|A A|2 2|3 3|6 6|J J|Q Q|K K|
±–±--±–±--±–±--±–±--±–±--±–±--±–+

解析:

我們可以把撲克牌playing cards想象成一個結構體card,包含pattern(花色)、figure(點數)。爲了方便本題操作,我們還給它加了belong(持有者,0、1、2、3代表4位玩家),再定義一個realnum把figure的字符表示的點數轉化爲方便比較的int型數據,其中A用14表示。
解決這題的思路爲:用deck[52]依次序記錄52張牌,這部分的重點是記錄好每張牌的belong(持有者)。之後,我們把這52張牌按花色分到card club[13],diamond[13],spade[13], heart[13]四種花色中。然後每個花色進行排序。
輸出時,因爲花色間的大小關係已經確定,對於每個玩家,依次輸出梅花、方片、黑桃、紅桃,因爲在上一步中每個花色已經排好,所以直接輸出即可。
這種思路針對特定的題,沒有按照多條件排序的做法做。

回顧:

本地樣例過了之後,VJ上一直是WA。經過研究,發現了錯誤所在。在輸入兩個長爲52的字符數組(char b1[52], b2[52])時,我剛開始直接採用了cin >> b1 >> b2的寫法,而這種寫法會導致部分編譯器將其視爲字符串,然後在最後一位加\0,這樣最後一位就丟失了。解決的辦法是把數組開大或者採用下面代碼中的逐個輸入的方法。

源碼:

#include<iostream>
using namespace std;

//(梅花C)<(方片D)<(黑桃S)<(紅桃H)
// 2 < 3 < 4 < 5 < 6 < 7 < 8 < 9 < T < J < Q < K < A
//North,East,South,West

struct card{
	char pattern; // 花色 
	char figure;  // 點數 
	int belong;   // 持有者 
	int realnum;  // 真值(把figure轉化爲int型) 
	
};

int main(){
	char a; // 發牌者 
	while(cin >> a)
	{
		if(a - '#' == 0)
			return 0;
		else
		{
			// 把52張牌寫進deck[52]裏
			char b1[52];
			char b2[52];
			
			for(int i = 0 ; i < 52 ; i++)
			{
				cin >> b1[i];
			 } 
			for(int i = 0 ; i < 52 ; i++)
			{
				cin >> b2[i];
			 } 
			
			int tag;
			if(a == 'N')
				tag = 0;
			if(a == 'E')
				tag = 1;
			if(a == 'S')
				tag = 2;
			if(a == 'W')
				tag = 3;
			
			// 聲明deck[52]保存輸入的五張牌 
			card deck[52];
			for(int i = 0 ; i < 26 ; i++)
			{
				deck[i].pattern = b1[2 * i];
				deck[i].figure = b1[2 * i + 1];
				deck[i].belong = (i + tag) % 4;
			}
			
			for(int i = 0 ; i < 26 ; i++)
			{
				deck[i + 26].pattern = b2[2 * i];
				deck[i + 26].figure = b2[2 * i + 1];
				deck[i + 26].belong = (i + 2 + tag) % 4;	
			}
			
			for(int i = 0 ; i < 52 ; i++)
			{
				if(deck[i].figure - '2' <= 7)
					deck[i].realnum = deck[i].figure - '0';
				else
				{
					if(deck[i].figure - 'T' == 0)
						deck[i].realnum = 10;
					if(deck[i].figure - 'J' == 0)
						deck[i].realnum = 11;
					if(deck[i].figure - 'Q' == 0)
						deck[i].realnum = 12;
					if(deck[i].figure - 'K' == 0)
						deck[i].realnum = 13;
					if(deck[i].figure - 'A' == 0)
						deck[i].realnum = 14;
				}
			}
			
			// 按花色分出來然後同一花色按大小排序,因爲card類型裏有belong表示牌的所屬
			// 最後直接按belong的值就能取出來輸出 
			card club[13];
			card diamond[13];
			card spade[13];
			card heart[13];
			
			int tag1 = 0, tag2 = 0, tag3 = 0, tag4 = 0;
			for(int i = 0 ; i < 52 ; i++)
			{
				
				if(deck[i].pattern - 'C' == 0)
				{
					club[tag1] = deck[i];
					tag1++;
				}
				if(deck[i].pattern - 'D' == 0)
				{
					diamond[tag2] = deck[i];
					tag2++;
				}
				if(deck[i].pattern - 'S' == 0)
				{
					spade[tag3] = deck[i];
					tag3++;
				}
				if(deck[i].pattern - 'H' == 0)
				{
					heart[tag4] = deck[i];
					tag4++;
				}
			}
			
			// 冒泡排序,把每個花色的牌按點數大小排序 
			for(int i = 0 ; i < 12 ; i++)
			{
				for(int j = 0 ; j < 12 ; j++)
				{
					if(club[j].realnum > club[j + 1].realnum)
					{
						card tmp;
						tmp = club[j];
						club[j] = club[j + 1];
						club[j + 1] = tmp;
					}
				}
				for(int j = 0 ; j < 12 ; j++)
				{
					if(diamond[j].realnum > diamond[j + 1].realnum)
					{
						card tmp;
						tmp = diamond[j];
						diamond[j] = diamond[j + 1];
						diamond[j + 1] = tmp;
					}
				}
				for(int j = 0 ; j < 12 ; j++)
				{
					if(spade[j].realnum > spade[j + 1].realnum)
					{
						card tmp;
						tmp = spade[j];
						spade[j] = spade[j + 1];
						spade[j + 1] = tmp;
					}
				}
				for(int j = 0 ; j < 12 ; j++)
				{
					if(heart[j].realnum > heart[j + 1].realnum)
					{
						card tmp;
						tmp = heart[j];
						heart[j] = heart[j + 1];
						heart[j + 1] = tmp;
					}
				}
			}
			
			// 剩下的就是輸出部分了 各種重複 原理是遍歷四個花色的數組,找出belong是0/1/2/3的分別輸出 
			cout << "South player:" << endl;
			cout << "+---+---+---+---+---+---+---+---+---+---+---+---+---+" <<endl;
			for(int i = 0 ; i < 13 ; i++)
				if(club[i].belong == 1)
					cout << "|" << club[i].figure << " " << club[i].figure;
			for(int i = 0 ; i < 13 ; i++)
				if(diamond[i].belong == 1)
					cout << "|" << diamond[i].figure << " " << diamond[i].figure;
			for(int i = 0 ; i < 13 ; i++)
				if(spade[i].belong == 1)
					cout << "|" << spade[i].figure << " " << spade[i].figure;
			for(int i = 0 ; i < 13 ; i++)
				if(heart[i].belong == 1)
					cout << "|" << heart[i].figure << " " << heart[i].figure;
			cout << "|" << endl;	

			for(int i = 0 ; i < 13 ; i++)
				if(club[i].belong == 1)
					cout << "|" << " " << club[i].pattern << " ";
			for(int i = 0 ; i < 13 ; i++)
				if(diamond[i].belong == 1)
					cout << "|" << " " << diamond[i].pattern << " ";
			for(int i = 0 ; i < 13 ; i++)
				if(spade[i].belong == 1)
					cout << "|" << " " << spade[i].pattern << " ";
			for(int i = 0 ; i < 13 ; i++)
				if(heart[i].belong == 1)
					cout << "|" << " " << heart[i].pattern << " ";	
			cout << "|" << endl;
			
			for(int i = 0 ; i < 13 ; i++)
				if(club[i].belong == 1)
					cout << "|" << club[i].figure << " " << club[i].figure;
			for(int i = 0 ; i < 13 ; i++)
				if(diamond[i].belong == 1)
					cout << "|" << diamond[i].figure << " " << diamond[i].figure;
			for(int i = 0 ; i < 13 ; i++)
				if(spade[i].belong == 1)
					cout << "|" << spade[i].figure << " " << spade[i].figure;
			for(int i = 0 ; i < 13 ; i++)
				if(heart[i].belong == 1)
					cout << "|" << heart[i].figure << " " << heart[i].figure;
			cout << "|" << endl;
			cout << "+---+---+---+---+---+---+---+---+---+---+---+---+---+" <<endl;
			
			// 
			cout << "West player:" << endl;
			cout << "+---+---+---+---+---+---+---+---+---+---+---+---+---+" <<endl;
			for(int i = 0 ; i < 13 ; i++)
				if(club[i].belong == 2)
					cout << "|" << club[i].figure << " " << club[i].figure;
			for(int i = 0 ; i < 13 ; i++)
				if(diamond[i].belong == 2)
					cout << "|" << diamond[i].figure << " " << diamond[i].figure;
			for(int i = 0 ; i < 13 ; i++)
				if(spade[i].belong == 2)
					cout << "|" << spade[i].figure << " " << spade[i].figure;
			for(int i = 0 ; i < 13 ; i++)
				if(heart[i].belong == 2)
					cout << "|" << heart[i].figure << " " << heart[i].figure;
			cout << "|" << endl;	

			for(int i = 0 ; i < 13 ; i++)
				if(club[i].belong == 2)
					cout << "|" << " " << club[i].pattern << " ";
			for(int i = 0 ; i < 13 ; i++)
				if(diamond[i].belong == 2)
					cout << "|" << " " << diamond[i].pattern << " ";
			for(int i = 0 ; i < 13 ; i++)
				if(spade[i].belong == 2)
					cout << "|" << " " << spade[i].pattern << " ";
			for(int i = 0 ; i < 13 ; i++)
				if(heart[i].belong == 2)
					cout << "|" << " " << heart[i].pattern << " ";	
			cout << "|" << endl;
			
			for(int i = 0 ; i < 13 ; i++)
				if(club[i].belong == 2)
					cout << "|" << club[i].figure << " " << club[i].figure;
			for(int i = 0 ; i < 13 ; i++)
				if(diamond[i].belong == 2)
					cout << "|" << diamond[i].figure << " " << diamond[i].figure;
			for(int i = 0 ; i < 13 ; i++)
				if(spade[i].belong == 2)
					cout << "|" << spade[i].figure << " " << spade[i].figure;
			for(int i = 0 ; i < 13 ; i++)
				if(heart[i].belong == 2)
					cout << "|" << heart[i].figure << " " << heart[i].figure;
			cout << "|" << endl;
			cout << "+---+---+---+---+---+---+---+---+---+---+---+---+---+" <<endl;
			
			//
			cout << "North player:" << endl;
			cout << "+---+---+---+---+---+---+---+---+---+---+---+---+---+" <<endl;
			for(int i = 0 ; i < 13 ; i++)
				if(club[i].belong == 3)
					cout << "|" << club[i].figure << " " << club[i].figure;
			for(int i = 0 ; i < 13 ; i++)
				if(diamond[i].belong == 3)
					cout << "|" << diamond[i].figure << " " << diamond[i].figure;
			for(int i = 0 ; i < 13 ; i++)
				if(spade[i].belong == 3)
					cout << "|" << spade[i].figure << " " << spade[i].figure;
			for(int i = 0 ; i < 13 ; i++)
				if(heart[i].belong == 3)
					cout << "|" << heart[i].figure << " " << heart[i].figure;
			cout << "|" << endl;	

			for(int i = 0 ; i < 13 ; i++)
				if(club[i].belong == 3)
					cout << "|" << " " << club[i].pattern << " ";
			for(int i = 0 ; i < 13 ; i++)
				if(diamond[i].belong == 3)
					cout << "|" << " " << diamond[i].pattern << " ";
			for(int i = 0 ; i < 13 ; i++)
				if(spade[i].belong == 3)
					cout << "|" << " " << spade[i].pattern << " ";
			for(int i = 0 ; i < 13 ; i++)
				if(heart[i].belong == 3)
					cout << "|" << " " << heart[i].pattern << " ";	
			cout << "|" << endl;
			
			for(int i = 0 ; i < 13 ; i++)
				if(club[i].belong == 3)
					cout << "|" << club[i].figure << " " << club[i].figure;
			for(int i = 0 ; i < 13 ; i++)
				if(diamond[i].belong == 3)
					cout << "|" << diamond[i].figure << " " << diamond[i].figure;
			for(int i = 0 ; i < 13 ; i++)
				if(spade[i].belong == 3)
					cout << "|" << spade[i].figure << " " << spade[i].figure;
			for(int i = 0 ; i < 13 ; i++)
				if(heart[i].belong == 3)
					cout << "|" << heart[i].figure << " " << heart[i].figure;
			cout << "|" << endl;
			cout << "+---+---+---+---+---+---+---+---+---+---+---+---+---+" <<endl;
			
			//
			cout << "East player:" << endl;
			cout << "+---+---+---+---+---+---+---+---+---+---+---+---+---+" <<endl;
			for(int i = 0 ; i < 13 ; i++)
				if(club[i].belong == 0)
					cout << "|" << club[i].figure << " " << club[i].figure;
			for(int i = 0 ; i < 13 ; i++)
				if(diamond[i].belong == 0)
					cout << "|" << diamond[i].figure << " " << diamond[i].figure;
			for(int i = 0 ; i < 13 ; i++)
				if(spade[i].belong == 0)
					cout << "|" << spade[i].figure << " " << spade[i].figure;
			for(int i = 0 ; i < 13 ; i++)
				if(heart[i].belong == 0)
					cout << "|" << heart[i].figure << " " << heart[i].figure;
			cout << "|" << endl;	

			for(int i = 0 ; i < 13 ; i++)
				if(club[i].belong == 0)
					cout << "|" << " " << club[i].pattern << " ";
			for(int i = 0 ; i < 13 ; i++)
				if(diamond[i].belong == 0)
					cout << "|" << " " << diamond[i].pattern << " ";
			for(int i = 0 ; i < 13 ; i++)
				if(spade[i].belong == 0)
					cout << "|" << " " << spade[i].pattern << " ";
			for(int i = 0 ; i < 13 ; i++)
				if(heart[i].belong == 0)
					cout << "|" << " " << heart[i].pattern << " ";	
			cout << "|" << endl;
			
			for(int i = 0 ; i < 13 ; i++)
				if(club[i].belong == 0)
					cout << "|" << club[i].figure << " " << club[i].figure;
			for(int i = 0 ; i < 13 ; i++)
				if(diamond[i].belong == 0)
					cout << "|" << diamond[i].figure << " " << diamond[i].figure;
			for(int i = 0 ; i < 13 ; i++)
				if(spade[i].belong == 0)
					cout << "|" << spade[i].figure << " " << spade[i].figure;
			for(int i = 0 ; i < 13 ; i++)
				if(heart[i].belong == 0)
					cout << "|" << heart[i].figure << " " << heart[i].figure;
			cout << "|" << endl;
			cout << "+---+---+---+---+---+---+---+---+---+---+---+---+---+" <<endl;
			
		}
		cout << endl;
	}
} 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章