1. 程式人生 > >【 OJ 】 HDOJ1022 18年10月31日21:41 [ 21 ]

【 OJ 】 HDOJ1022 18年10月31日21:41 [ 21 ]

這題蛋疼......開始看題目以為只要判斷是否逆序就出來了,後來發現人家網上說【並不是說必須所有的車都進站了  才可以統一按順序出來,而是說可以先進入一輛車然後這輛車出來,然後再進下一輛車,也可以先進兩輛然後出來一輛再進一輛,即何時進站何時出站都可以....】才恍然大悟....

所以這題思路就很明確了,只要看出棧的順序即可,如題目:入棧串 O1  出棧串O2 棧用STACK表示

所以基本思路就是:

注:中途出現棧中數量為9但是依然需要push也是no,題意說車站(棧)最多進9個列車

(1):看O2的第一個元素是啥,假如是3,那麼就讀取入棧O1,直到讀取到3為止(或者讀取超過9個失敗輸出"no"),將3入棧再出棧(模擬了入車站,出車站)

(2)重複步驟 1(第一個元素下標換成下一個) =>速度加快判斷可以去 (3)

(3)做完步驟(1)【這時候就要看O2的第二個元素是啥,假設是4,那麼看這個元素是否已經在棧中,如果已經在棧中,那麼看它是否是棧的top元素,如果不是說明"no"(此類情況出現可以直接得出結論,加速判斷) 因為現在出棧O2要出4,但是棧中有一個元素在4前面,(為了方便理解假設現在top是2)那麼4要出來2一定要出來,而且2出在了4的前面,因此肯定是不合適的....如果top元素就是現在O2要出的,那麼好辦就把它出棧出來即可】,返回步驟(1)[此時直接返回步驟即可,O2下一個元素是不是在棧中已經不重要,如果在棧中,那麼棧要麼會超過9個失敗,或者O1順序全部進棧...退出第二個while,到達下面的if被find發現失敗]

//雖然這個程式碼被AC了但是仔細的思考,感覺邏輯有漏洞 [= =~]

如果是步驟(1)做完,返回繼續進行步驟(1),有沒有這種情況發生,就是 a 元素已經在棧中,並且不是top元素,那麼讀取O1元素和O2下一個元素比較的時候,會由於兩個元素不一樣而一直入棧,此時會有2種情況:

a.超過9列失敗

b.沒有9列車,但是O1被讀取光了...發生越界....

所以 while (STACK_idenx<9&&O1_index<n&&STACK[STACK_idenx] != O2[O2_index]) //加上了對於O1界限的限制

然後此時依舊有問題,對於第一層的while(O2_index<n)的判斷標準依舊是合法的無限死迴圈....但是此種情況已經是失敗的....

所以....突然發現....虛線部分是可以拯救世界的.....此種情況(已在棧中並且非棧頂元素)可以break

---------------------------------------------------------------------------------------------------------------------------------

綜上所述: 

 while (STACK_idenx<9&&O1_index<n&&STACK[STACK_idenx] != O2[O2_index]) //加上了對於O1界限的限制

虛線部分不刪除,即可

# include<iostream>
using namespace std;
char O1[1000];//入棧
char O2[1000];//出棧
char STACK[9];//模擬車站最多隻有9列
bool Path[2000];// 0 入棧 1 出棧
bool find(char*s, int n, char a) {
    int i ;
    for (i = n; i >= 0; i--) {
        if (s[i] == a)
            return true;
    }
    return false;
}
int main(void) {
    int n,O1_index,O2_index,STACK_idenx,Path_index;
    bool IS_OK;
    while (cin >> n) {
        cin >> O1 >> O2;
        O1_index = O2_index = STACK_idenx = Path_index = 0;
        IS_OK = true;
        while (O2_index < n) {//檢查的條件 出棧順序陣列沒空 
            if (!O1_index) {//將第一個數入棧
                STACK[STACK_idenx] = O1[O1_index++];
                Path[Path_index++] = 0;
            }
            while (STACK_idenx<9&&O1_index<n&&STACK[STACK_idenx] != O2[O2_index])
 {//原錯誤寫法: while (STACK_idenx<9&&STACK[STACK_idenx] != O2[O2_index])
//(1)棧中還能push(2)還有入棧元素(3)棧頂不等於出棧順序
                //並不等於出棧的列車
                STACK_idenx++;
                STACK[STACK_idenx] = O1[O1_index++];//將第二數字繼續入棧
                Path[Path_index++] = 0;//記錄入棧的路徑
            }//最終必然找到了和出棧順序一樣的(或者站滿)
            if (STACK[STACK_idenx] == O2[O2_index++]) {//如果棧頂元素等於出棧元素
                Path[Path_index++] = 1;//出棧
                STACK_idenx--;
            }
            if (STACK_idenx == 9)
            { 
                IS_OK = false;
                break;
            }
//虛線處不寫,不影響AC,但是影響邏輯正確性,而且可以加快判斷
//-----------------------------------------------------------
            if (O2_index < n) {//出棧順序下標合法
                if (find(STACK, STACK_idenx, O2[O2_index])) {//此時檢查出棧的下個數字是否在棧中(前提出棧數本身在合法範圍內)
                    if (STACK[STACK_idenx] == O2[O2_index++]) {
                        //現在的出棧元素就是原來出棧佇列的下一個數字,出棧
                        Path[Path_index++] = 1;
                        STACK_idenx--;
                    }
                    else {//出現此種情況可以快速出來,減少了很多次入棧
                        IS_OK = false;
                        break;
                    }
                }//else繼續進行while() push 進棧
            }//檢查是否出棧順序下標合法
//------------------------------------------------------------
        }
        if (IS_OK) {
            cout << "Yes." << endl;
            for (int i = 0; i < Path_index; ++i)
                if (Path[i])
                    cout << "out" << endl;
                else
                    cout << "in" << endl;
            cout << "FINISH" << endl;
        }
        else {
            cout << "No." << endl;
            cout << "FINISH" << endl;
        }
    }
    system("pause");
    return 0;
}

下面這份程式碼是用棧寫的一次....特麼WA了....並沒有啥問題....

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

int main(void) {
	stack<char>STACK;
	int n;
	char O1[1000];
	char O2[1000];
	bool Path[2000];
	bool IS_OK;// 0入 1 出
	int O1_i, O2_i, P_i, i;
	while (cin >> n) {
		cin >> O1 >> O2;
		O1_i = O2_i = P_i = 0;
		IS_OK = true;
		memset(Path, 0, sizeof(Path));
		STACK.push(O1[O1_i++]);//將第一個元素入棧
		Path[P_i++] = 0;
		while (O2_i < n) {
			while (O1_i < n&&STACK.size() < 9 && STACK.top() != O2[O2_i]) {
				STACK.push(O1[O1_i++]);
				Path[P_i++] = 0;
			}
			if (STACK.top() == O2[O2_i]) {//棧頂元素等於出棧元素
				O2_i++;//必須裡面自加
				STACK.pop();
				Path[P_i++] = 1;
			}
			if (STACK.size() == 9) {//棧滿失敗
				IS_OK = false;
				break;
			}
			if (O1_i == n) {//所有元素全部入棧了
				if (O2_i < n) {
					if (STACK.top() != O2[O2_i]) {
						IS_OK = false;
						break;
					}
					else {//棧頂就是出棧
						STACK.pop();
						Path[P_i++] = 1;
						O2_i++;
					}
				}
			}
		}//while(O2_i<n)
		if (IS_OK) {
			cout << "Yes." << endl;
			for ( i = 0; i < P_i; ++i)
				if (Path[i])
					cout << "out" << endl;
				else
					cout << "in" << endl;
		}
		else
			cout << "No." << endl;
		cout << "FINISH" << endl;
	}
	system("pause");
	return 0;
}