訓練賽後補題 04
2020-06-29 個人訓練賽後補題
補題補到心態炸裂……嗚嗚嗚怎麼沒寫的這麼多啊
我好菜
好了開始補題:
QAQ完全沒發現自己錯在哪的第一個提交
WA的程式碼:
1 #pragma warning (disable:4996) 2 #include <iostream> 3 #include<algorithm> 4 #include<stdio.h> 5 #include<math.h> 6 #include<string.h> 7 #include<string> 8 #defineMAX1 100005 /*1e5 + 5*/ 9 #define MAX2 1000000005 /*le9 + 5*/ 10 #define MAX3 200005 /*1e5 + 5*/ 11 #define MAX4 5005 /*5e4 + 5*/ 12 #define T2 27 13 #define T3 18 14 using namespace std; 15 typedef long long int ll; 16 #define MOL 998244353 17 18 int main() { 19 int n, k, a[MAX4] = { 0}, i; 20 while (scanf("%d %d", &n, &k) != EOF) { 21 for (i = 1; i <= n; ++i) { 22 scanf("%d", &a[i]); 23 } 24 int j, t = 0, ans, flag; 25 ans = 0; 26 for (i = 1; i <= n;) { 27 //cout << i << ":" << a[i] << endl;28 j = 0; 29 flag = 0; 30 if (a[i]) { 31 i += k; //pass 32 ans++; //help+1 33 } 34 else { 35 flag = 1; 36 t = i; 37 j = i + k - 1; 38 while (j > t) { 39 if (a[j]) { 40 i = j; 41 flag = 0; 42 break; 43 } 44 j--; 45 } 46 } 47 if (flag) { 48 break; 49 } 50 } 51 if (flag || ans == 0)printf("-1\n"); 52 else printf("%d\n", ans); 53 } 54 return 0; 55 }
我太難了55555
////-------------------------------------
去了原題cf看了樣例,明白我錯在哪了……a[i]=0的時候檢索區域大小不應該是k-1,應該是2k-1……
用
6 2
0 1 1 0 0 1
這個資料就不能通過……
可見測試資料範圍的重要性
////-------------------------------------
我又又又又叕叒雙WA了,WA在了test 5
這次的主函式:
1 int main() { 2 int n, k, a[MAX4] = { 0 }, i; 3 while (scanf("%d %d", &n, &k) != EOF) { 4 for (i = 1; i <= n; ++i) { 5 scanf("%d", &a[i]); 6 } 7 int j, t = 0, ans, flag; 8 ans = 0; 9 for (i = 1; i <= n;) { 10 //cout << i << ":" << a[i] << endl; 11 j = 0; 12 flag = 0; 13 if (a[i]) { 14 i += k; 15 ans++; //help+1 16 } 17 else { 18 flag = 1; 19 if (i > k) 20 t = i - k; 21 else 22 t = i; 23 if (i + k - 2 < n) 24 j = i + k - 1; 25 else j = n; 26 while (j > t) { 27 if (a[j]) { 28 i = j + k; 29 ans++; 30 flag = 0; 31 break; 32 } 33 j--; 34 } 35 } 36 if (flag) { 37 break; 38 } 39 } 40 if (flag || ans == 0)printf("-1\n"); 41 else printf("%d\n", ans); 42 } 43 return 0; 44 }
這次的失敗樣例是:
【太長了網站沒給全】
1000 100 0 1……正答6,輸出8
emmmm我瞅瞅咋多了
emmm這份程式碼邏輯有個隱患,就是:程式碼本身是每次往後檢索最遠的接應點,但是對於樣例,可能部分挨著的接應點能滿足更少的數量……總之就是極端樣例不通過。
so我去看了題解……我真的真的恨不熟練貪心。
還能怎麼辦呢,學唄。
////------------------堅定自己程式碼邏輯有實現可能的我賊心不死,又去修改原先的程式碼了
這次能通過了,但是超時了【泣不成聲】
以下是在樣例10超時的程式碼:
1 #pragma warning (disable:4996) 2 #include <iostream> 3 #include<algorithm> 4 #include<stdio.h> 5 #include<math.h> 6 #include<string.h> 7 #include<string> 8 #define MAX1 100005 /*1e5 + 5*/ 9 #define MAX2 1000000005 /*le9 + 5*/ 10 #define MAX3 200005 /*1e5 + 5*/ 11 #define MAX4 5005 /*5e4 + 5*/ 12 #define T2 27 13 #define T3 18 14 using namespace std; 15 typedef long long int ll; 16 #define MOL 998244353 17 18 int main() { 19 int n, k, a[MAX4] = { 0 }, i, flag = 0; 20 while (scanf("%d %d", &n, &k) != EOF) { 21 for (i = 1; i <= n; ++i) { 22 scanf("%d", &a[i]); 23 } 24 int rf, lf = 0, ans, flag = 0; 25 ans = 0; 26 for (i = 1; i <= n;) { //從前方洞穴往後檢測 27 //失誤點:第一個風洞非必要選擇 28 //cout << i << ":" << a[i] << endl; 29 rf = 0; 30 flag = 1; //假設前後風洞都不能使當前洞可走 31 if (i > k) //前方最遠風洞距離限制 32 lf = i - k; 33 else 34 lf = 1; 35 if (i + k - 2 < n) //後方最遠風洞距離限制 36 rf = i + k - 1; 37 else 38 rf = n; 39 while (rf >= lf) { //從後方往前檢測 40 if (a[rf]) { //檢測到風洞 41 i = rf + k; //下一監測點為風洞影響範圍外鄰點 42 ans++; //所用風洞數+1 43 flag = 0; //這一段路可走了 44 break; //暫停檢測,進入下一監測點 45 } 46 rf--; 47 } 48 //cout << "check finished" << endl;//test 49 if (flag) { //出現沒有前後風洞能接力的洞,退出檢測 50 break; 51 } 52 } 53 if (flag || ans == 0)printf("-1\n"); 54 else printf("%d\n", ans); 55 } 56 return 0; 57 }
emmmm接下來按照這個邏輯優化試試
總結一下邏輯規律:每次找出範圍內的最後一個風洞,不過是從前往後
臥槽,這……這本質上就是貪心啊【驚】
////----------------7.04更新!我終於AC辣!!!
尤其是,我發現我離AC只有一步之遙——沒錯把其中一個順序調換一下,就不需要多餘的檢測了!
下面是AC程式碼,我太難了55555
不過AC了真高興
1 #pragma warning (disable:4996) 2 #include <iostream> 3 #include<algorithm> 4 #include<stdio.h> 5 #include<math.h> 6 #include<string.h> 7 #include<string> 8 #define MAX1 100005 /*1e5 + 5*/ 9 #define MAX2 1000000005 /*le9 + 5*/ 10 #define MAX3 200005 /*1e5 + 5*/ 11 #define MAX4 5005 /*5e4 + 5*/ 12 #define T2 27 13 #define T3 18 14 using namespace std; 15 typedef long long int ll; 16 #define MOL 998244353 17 18 int main() { 19 int n, k, a[MAX4] = { 0 }, s[MAX4] = { 0 }, i, flag = 0; 20 while (scanf("%d %d", &n, &k) != EOF) { 21 for (i = 1; i <= n; ++i) { 22 scanf("%d", &a[i]); 23 s[i] = s[i - 1] + a[i]; //前幾個洞中有多少風洞 24 } 25 int rf, lf = 0, ans, flag = 0; 26 ans = 0; 27 for (i = 1; i <= n;) { //從前方洞穴往後檢測 28 //失誤點:第一個風洞非必要選擇 29 //cout << i << ":" << a[i] << endl; 30 rf = 0; 31 flag = 1; //假設前後風洞都不能使當前洞可走 32 if (i > k - 1) //前方最遠風洞距離限制 33 lf = i - k + 1; 34 else 35 lf = 1; 36 if (i + k - 2 < n) //後方最遠風洞距離限制 37 rf = i + k - 1; 38 else 39 rf = n; 40 if (s[rf] - s[lf - 1] == 0) //距離限制範圍內無風洞,退出檢測 41 break; 42 else 43 while (rf >= lf) { //從後方往前檢測 44 if (a[rf]) { //檢測到風洞 45 i = rf + k; //下一監測點為風洞影響範圍外鄰點 46 ans++; //所用風洞數+1 47 flag = 0; //這一段路可走了 48 break; //暫停檢測,進入下一監測點 49 } 50 rf--; 51 } 52 //cout << "check finished" << endl;//test 53 } 54 if (flag || ans == 0)printf("-1\n"); 55 else printf("%d\n", ans); 56 } 57 return 0; 58 }
////------------------7.06更新……隊裡大佬說自己打出題要比照著題解打好很多,嘿嘿嘿我也這麼覺得。
我這次認真查了一下貪心
強烈安利一個大佬哦,部落格寫得超級好理解
網址:https://blog.csdn.net/jxhaha/article/details/78762412
另外我還做了些筆記:
活動選擇:對於互斥不可重複活動,始終選取結束時間最早的活動作為解集合成員,每次抽取結束時間最早的活動。
0 - 1揹包:F[i,j] = max(F[i-1,j],F[i-1,j-Wi]+Vi) 適用:每個物體只抽一次取最大重量方案
完全揹包:F[i,j]=max(f[i-1,j], f[i,j-Wi]+Vi) 適用:能多次選擇同一物體取最大重量
多重揹包:F[i,j] = max(F[i-1,j],F[i, j-Wi*k]+Vi*k 適用:規定次數內可選同一物品時取最大重量
膜拜大佬!