日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

算法竞赛入门经典(第二版) | 例题4-5 追踪电子表格中的单元格 (UVa512,Spreadsheet Tracking,World Finals)(解法一)

發布時間:2024/2/28 编程问答 43 豆豆
生活随笔 收集整理的這篇文章主要介紹了 算法竞赛入门经典(第二版) | 例题4-5 追踪电子表格中的单元格 (UVa512,Spreadsheet Tracking,World Finals)(解法一) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

大意

輸入:r(行)c(列)n(種操作)m(個行/列),給出具體行/列 x(個坐標),給出具體坐標。
輸出:m個坐標經過n種操作后分別移動到了哪里。
注意:所有操作都是根據原始表進行的,如:1,2,3行前插入空行,此123行指原表的123行,而不是插入一行后值變動。

輸入輸出格式:

1、輸入m和n其一得零時結束。每個輸出結果直接無空行。
2、每個輸出之前需要有空行,且最后一個輸出前沒空行。

分析:

核心難點在于如何在插入和刪除時,每次操作都是相對于原表進行的。
我的失敗思路:
1、若刪除多行/列,如何判斷刪除的是原始表中的行或列?
先將所在行全部置零,全遍歷完后,統一刪除為0的行。 注意判斷條件要用while,if檢測不到連續行為0的情況
注意邊界條件!!!!!!!若最后一行/列為0,直接自減,跳過循環, 否則會先入死循環
2、行和列的刪除解決了,如何判斷插入的是原始表中的行和列?
到這里我就卡住了,思考再三,覺得再繼續下去學到的東西也不多了, 于是開始理解劉先生的代碼。(后來仔細看題,其實是我漏掉了一個值,導致無法知道接下來要輸入多少數字,如果用數組的方式應該也可以做出來。)
劉先生的正確思路:
劉先生的刪除是將待刪的行、列存入數組, 給d賦值時,加一層篩選,若是數組里的行、列數,則取消賦值。
插入則是多插一層0,0。


傳送門→UVa-512
沒使用過該網站的同學請猛戳這里→vJudge教程
百度翻譯→百度翻譯


代碼:

#include<stdio.h> #include<string.h> #define maxd 100 #define BIG 10000 int r, c, n, d[maxd][maxd], d2[maxd][maxd], ans[maxd][maxd], cols[maxd];void copy(char type, int p, int q) {if(type == 'R') {for(int i = 1; i <= c; i++)d[p][i] = d2[q][i];} else {for(int i = 1; i <= r; i++)d[i][p] = d2[i][q];} }void del(char type) {memcpy(d2, d, sizeof(d));int cnt = type == 'R' ? r : c, cnt2 = 0;for(int i = 1; i <= cnt; i++) {if(!cols[i]) copy(type, ++cnt2, i);}if(type == 'R') r = cnt2; else c = cnt2; }void ins(char type) {memcpy(d2, d, sizeof(d));int cnt = type == 'R' ? r : c, cnt2 = 0;for(int i = 1; i <= cnt; i++) {if(cols[i]) copy(type, ++cnt2, 0);copy(type, ++cnt2, i);}if(type == 'R') r = cnt2; else c = cnt2; }int main() {int r1, c1, r2, c2, q, kase = 0;char cmd[10];memset(d, 0, sizeof(d));while(scanf("%d%d%d", &r, &c, &n) == 3 && r) {int r0 = r, c0 = c;for(int i = 1; i <= r; i++)for(int j = 1; j <= c; j++)d[i][j] = i*BIG + j;while(n--) {scanf("%s", cmd);if(cmd[0] == 'E') {scanf("%d%d%d%d", &r1, &c1, &r2, &c2);int t = d[r1][c1]; d[r1][c1] = d[r2][c2]; d[r2][c2] = t;} else {int a, x;scanf("%d", &a);memset(cols, 0, sizeof(cols));for(int i = 0; i < a; i++) { scanf("%d", &x); cols[x] = 1; }if(cmd[0] == 'D') del(cmd[1]); else ins(cmd[1]);}}memset(ans, 0, sizeof(ans));for(int i = 1; i <= r; i++)for(int j = 1; j <= c; j++) {ans[d[i][j]/BIG][d[i][j]%BIG] = i*BIG+j;}if(kase > 0) printf("\n");printf("Spreadsheet #%d\n", ++kase);scanf("%d", &q);while(q--) {scanf("%d%d", &r1, &c1);printf("Cell data in (%d,%d) ", r1, c1);if(ans[r1][c1] == 0) printf("GONE\n");else printf("moved to (%d,%d)\n", ans[r1][c1]/BIG, ans[r1][c1]%BIG);}}return 0; }

收獲:

1、鞏固了調試技巧(設置輸出函數更加靈活, 標紅函數頭部看的更加清楚)
2、自頂向下的創建方法。思路清晰。
3、函數復用 , 我雖然寫了函數,但還是有些臃腫了,只相當于將一部分代碼搬到外面去了。 沒有達到復用的效果
而劉先生是判斷刪除or插入,此為一級復用;接下來將判斷出的結果送入二級復用
4、判斷回車是否被吸取干凈:cout << 1 << (char)getchar() << 1; //判斷回車是否被吸取干凈
5、插入、刪除皆可以0或其他代替,減少代碼量
6、a[i][j] = i*BIG + j;后, a[i][j]/BIG = i ; a[i][j]%BIG = j;好處是:若想對表插入或刪除,直接看數組中值是否等于cols中值。
7、每個輸出前有空行,但最后一個輸出前沒空行,采取“輸出前加空行的方法,且第一個輸出前無空行”的方法
8、同時刪除行、列:查表。
9、圖表等模式注意邊界值的運算。


最后,分享一條大牛的建議(對筆者受益匪淺):平時在做題的時候,一定要尋找最優解,而不是 ac 了就不管了,應該多看看別人的解法。


解法二傳送門→解法2

總結

以上是生活随笔為你收集整理的算法竞赛入门经典(第二版) | 例题4-5 追踪电子表格中的单元格 (UVa512,Spreadsheet Tracking,World Finals)(解法一)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。