生活随笔
收集整理的這篇文章主要介紹了
移动小球
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
移動小球
時間限制(普通/Java)?:?
1000 MS/?3000 MS?? ? ? ???運行內存限制 : 65536 KByte 總提交 : 995 ? ? ? ?? ? 測試通過 : 131? 題目描述
你有一些小球,從左到右依次編號為1,2,3,…,n,如下圖所示:
你可以執行兩種指令。其中A X Y表示把小球X移動到小球Y左邊,B X Y表示把小球X移動到小球Y右邊。指令保證合法,即X不等于Y。
例如,在初始狀態下執行A 1 4后,小球1被移動到小球4的左邊,如下圖所示:
如果再執行B 3 5,結點3將會移到5的右邊,如下圖所示:
輸入
輸入小球個數n。指令條數m和m條指令,注意,1≤n≤500000,0≤m≤100000。
輸出
從左到右輸出最后的小球序列。
樣例輸入
6?2
A?1?4
B?3?5
樣例輸出
2?1?4?5?3?6
在多數情況下,線性表都用它的順序存儲結構——數組很輕松實現,但對有些問題有時用它的鏈式存儲結構——鏈表更好。
移動小球。
你有一些小球,從左到右依次編號為1,2,3,…,n,
可以執行兩種指令。其中,AX Y表法把小球X移動到小球Y左邊,B X Y表示把小球X移動到小球Y右邊。指令保證合法,即X不等于Y。
例如,在初始狀態下執行A1 4后,小球被移動小球4的左邊。
如果再執行B 3 5,結點3將會移到5的右邊。
輸入小球個數n,指令條數m和n條指令,從左到右輸出最后的序列。注意,n可能高達500000,而m可能高達100000。
樣例輸入:
6?????2
A? 1? 4
B? 3? 5
樣例輸出:
2 1 4 5 3 6
【分析】
各個小球在邏輯上是相鄰的,因此可考慮把它們放在一個數組A中,所以完整的程序如下:
[cpp]?view plaincopyprint?
#include?<stdio.h>?? const?int?MAXN?=?1000;?? int?n,?A[MAXN];?? int?find(int?X)?? {?? ????for(int?i?=?1;?i?<=?n;?i++)?? ????????if(A[i]?==?X)?return?i;?? ????return?0;?? }?? void?shift_circular_left(int?a,?int?b)?? {?? ????int?t?=?A[a];?? ????for(int?i?=?a;?i?<?b;?i++)?? ????{?? ????????A[i]?=?A[i+1];?? ????}?? ????A[b]?=?t;?? }?? void?shift_circular_right(int?a,?int?b)?? {?? ????int?t?=?A[b];?? ????for(int?i?=?b;?i?>?a;?i--)?? ????{?? ????????A[i]?=?A[i-1];?? ????}?? ????A[a]?=?t;?? }?? int?main()?? {?? ????int?m,?X,?Y,?p,?q;?? ????char?type[9];?? ????scanf("%d%d",?&n,?&m);?? ????for(int?i?=?1;?i?<=?n;?i++)????? ????????A[i]?=?i;?? ????for(int?i?=?0;?i?<?m;?i++)?? ????{?? ????????scanf("%s%d%d",?type,?&X,?&Y);?? ????????p?=?find(X);?????????????????? ????????q?=?find(Y);?? ????????if(type[0]?==?'A')?? ????????{?? ????????????if(q?>?p)?? ????????????????shift_circular_left(p,?q-1);???? ????????????else?shift_circular_right(q,?p);?????????? ????????}?? ????????else?? ????????{?? ????????????if(q?>?p)?? ????????????????shift_circular_left(p,?q);????? ????????????else?shift_circular_right(q+1,?p);??????? ????????}?? ????}?? ????for(int?i?=?1;?i?<=?n;?i++)?? ????????printf("%d?",?A[i]);?? ????printf("\n");?? ????return?0;?? }??
?
對于上面的程序,當數據量很大時,代碼是否會超時。一般來說,可以用兩種方法判斷:測試和分析。
計時測試的方法在前面已講過,它的優點是原理簡單、可操作性強,缺點在于必須事先程序寫好——包括主程序和測試數據生成器。如果算法非常復雜,這是相當花時間的。
另一種方法是寫程序之前進行算法分析,估算時間效率,這種方法在第8章會詳細分析。不過現在可以直觀分析一下:如果反復執行B 1 n和A 1 2,每次都移動幾乎所有元素。元素個數和指令條數都那么大,移動總次數將是相當可觀的。
2、鏈式結構
[cpp]?view plaincopyprint?
#include?<stdio.h>?? #include<string.h>?? const?int?MAXN?=?1000;?? int?n,?left[MAXN],?right[MAXN];?? ?? ?? void?link(int?X,?int?Y)?? {?? ????right[X]?=?Y;?? ????left[Y]?=?X;?? }?? ?? int?main()?? {?? ????int?m,?X,?Y;?? ????char?type[9];?? ????scanf("%d%d",?&n,?&m);?? ????memset(left,0,sizeof(left));?? ????memset(right,0,sizeof(right));?? ????for(int?i?=?0;?i?<=?n;?i++)?? ????{?? ????????left[i]?=?i-1;?? ????????right[i]?=?i+1;?? ????}?? ?????? ????for(int?i?=?0;?i?<?m;?i++)?? ????{?? ????????scanf("%s%d%d",type,?&X,?&Y);?? ????????link(left[X],?right[X]);?? ????????if(type[0]?==?'A')?? ????????{?? ????????????link(left[Y],?X);??? ????????????link(X,?Y);?? ????????}?? ????????else?? ????????{?? ????????????link(X,?right[Y]);????? ????????????link(Y,?X);?? ????????}?? ????}?? ????for(int?w?=?right[0];?w?!=?n+1;?w?=?right[w])?? ?????????? ????????printf("%d?",?w);?? ????printf("\n");?? ????return?0;?? }??
總結
以上是生活随笔為你收集整理的移动小球的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。