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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

信息学奥赛一本通 1321:【例6.3】删数问题(Noip1994) | 洛谷 P1106 删数问题

發布時間:2025/3/17 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 信息学奥赛一本通 1321:【例6.3】删数问题(Noip1994) | 洛谷 P1106 删数问题 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

【題目鏈接】

ybt 1321:【例6.3】刪數問題(Noip1994)
洛谷 P1106 刪數問題

【題目考點】

1. 貪心

【解題思路】

解法1:每次找k+1個數中的最小值

假設我們從左向右掃描每位數字,分別判斷該位數字是否應該被刪掉。此時各位數字為:
d1d2...dnd_1d_2...d_nd1?d2?...dn?,要在其中刪掉kkk位數字。
刪掉k位后剩下n?kn-kn?k位數字,最高位數字為dxd_xdx?
如果不刪d1d_1d1?,最高位為d1d_1d1?;如果刪除d1d_1d1?不刪d2d_2d2?,最高位為d2d_2d2?;。。。
d1~dk+1d_1\sim d_{k+1}d1?dk+1?都可能成為最終數字是最高位。為了讓結果最小,最高位應該是這些數字中的最小值。
假設找到第一個最小值是dmd_mdm?,則刪掉d1~dm?1d_1\sim d_{m-1}d1?dm?1?,刪掉了m?1m-1m?1個數字,下面還要刪掉k?m+1k-m+1k?m+1個數字。接下來就是子問題:在dm+1~dnd_{m+1}\sim d_ndm+1?dn?中刪掉k?m+1k-m+1k?m+1個數字。
(如果找的不是第一個最小值,那么刪掉的數字中也許有與最小值相等的數字可以作為下一位)
該算法最大復雜度:O(nk)O(nk)O(nk)

解法2:刪掉比后面數字大的數字

考察兩個連續數位的數字d1d2d_1d_2d1?d2?,已知d1>d2d_1> d_2d1?>d2?
方案一:刪掉d1d_1d1?保留d2d_2d2?
方案二:保留d1d_1d1?
兩種方案下,最后d1d_1d1?d2d_2d2?會在同一個數位上。很明顯應該讓更小的d2d_2d2?在這一數位上。
不斷用當前數位和下一位比較,如果當前數位大于下一位,那么刪除當前位。當前位置指向前一個位置。最后如果剩余幾位沒刪完,則從末尾開始刪除這些數位。
該算法最大復雜度:O(n)O(n)O(n)
【注意】:去除前導0

【題解代碼】

解法1:每次找k+1個數中的最小值

#include<bits/stdc++.h> using namespace std; #define N 300 int main() {int k, an = 0; char s[N], a[N];cin >> s >> k;int len = strlen(s), i;for(i = 0; i < len && s[i] == '0'; ++i);//去除前導0 while(i < len){if(k == len-i)//如果剩下的元素個數只有k個,那么都刪掉 break;int mi = i;//求i~i+k的最小值下標 for(int j = i; j <= i+k; ++j){if(s[j] < s[mi])mi = j;}a[++an] = s[mi];k -= mi - i;//s[i]~s[mi-1]都刪掉,刪掉了mi-i個元素i = mi + 1;}for(i = 1; i <= an && a[i] == '0'; ++i);//去除前導0 if(i > an)//如果前導0去完,就沒有可以輸出的了,說明原來的結果是0 cout << "0";elsewhile(i <= an)cout << a[i++];return 0; }

解法2:刪掉比后面數字大的數字

#include<bits/stdc++.h> using namespace std; #define N 300 int main() {int k, an = 0; char s[N], a[N];cin >> s >> k;int len = strlen(s), i, ct = 0;for(i = 0; i < len && s[i] == '0'; ++i);//去除前導0 for(; i < len; ++i){while(an > 0 && a[an] > s[i] && ct < k){an--;ct++;}a[++an] = s[i]; }while(ct < k)//刪除末尾的k-ct個元素{an--;ct++;}for(i = 1; i <= an && a[i] == '0'; ++i);//去除前導0 if(i > an)//如果前導0去完,就沒有可以輸出的了,說明原來的結果是0 cout << "0";elsewhile(i <= an)cout << a[i++];return 0; }

總結

以上是生活随笔為你收集整理的信息学奥赛一本通 1321:【例6.3】删数问题(Noip1994) | 洛谷 P1106 删数问题的全部內容,希望文章能夠幫你解決所遇到的問題。

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