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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

高楼扔鸡蛋

發布時間:2024/10/8 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 高楼扔鸡蛋 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

動態規劃:高樓扔雞蛋:

文章目錄

    • 高樓雞蛋進階
    • 二分優化
    • 重定義狀態轉移(我感覺上次應該是忘寫了)

題目:
*你面前有一棟從 1 到N共N層的樓,然后給你K個雞蛋(K至少為 1)。現在確定這棟樓存在樓層0 <= F <= N,在這層樓將雞蛋扔下去,雞蛋恰好沒摔碎(高于F的樓層都會碎,低于F的樓層都不會碎)。現在問你,最壞情況下,你至少要扔幾次雞蛋,才能確定這個樓層F呢? *
思考點:
dp min res=是對每一層都算一下,求最小次數
用字典做備忘錄不錯,但這里用數組也可,而且不用這種方法?剪枝?,會爆炸
但每一次[遞歸的每一層]又要取最大值,因為最壞情況
有兩個錯誤:忘寫了等于號,和記錄防止重復計算的數組應寫在循環外面

#include <iostream> #include<bits/stdc++.h> using namespace std; struct aa{ int k; int n; }; map<aa,int>dic; int dic2[1000][1000]={0}; int dp(int k,int n){if(k==1){return n;}if(n==0){return 0;}// if(dic[{k,n}]){// return dic[{k,n}];// }if(dic2[k][n]!=0){return dic2[k][n];}int res=10000;for(int i=1;i<=n;i++){int dpsui,dpweisui;///等價于下面的模塊留下來因為出錯了dpsui=dp(k-1,i-1);dpweisui=dp(k,n-i);if(dpsui>=dpweisui){///要寫等于號res=min(res,dpsui+1);// dic[{k,n}]=res;}if(dpsui<dpweisui){res=min(res,dpweisui+1);// dic[{k,n}]=res;}///等價于上面的模塊///res=min(res,max(dp(k,n-i),dp(k-1,i-1))+1);}dic2[k][n]=res; ///應該寫在循環外面return res; } int main() {int k=2,n=100;cout<<dp(k,n);return 0; }

2020.9.10寫出來的代碼:

#include <iostream> #include<bits/stdc++.h> using namespace std; int dp[105][105]={0}; int finder(int k,int n){/k:jidanshu n:loucengshuif(dp[k][n]!=0){return dp[k][n];} if(n==0)return 0; if(k==1)return n;int res=10000; zuo:suile you:meisui for(int i=1;i<=n;i++){res=min(res,max(finder(k-1,i-1),finder(k,n-i))+1); } dp[k][n]=res; return res; } int main() {cout<<finder(2,100);return 0; }

2020.11.13

#include <iostream> #include<bits/stdc++.h> /* run this program using the console pauser or add your own getch, system("pause") or input loop */ using namespace std; #define maxn 10005 int mem[maxn][maxn]={0};int dp(int k,int n) {if(k==1){return n;}if(n==0){return 0;}if(mem[k][n]!=0){return mem[k][n];}int res=maxn;for(int i=1;i<=n;i++){res=min(res,max(//這樣也能過編譯 dp(k-1,i-1),//sui//錯誤原因,這里之前沒i-1 dp(k,n-i))+1//unsui);}mem[k][n]=res;return mem[k][n]; }int main(int argc, char** argv) {cout<<dp(2,100);return 0; }//out::14

高樓雞蛋進階

高樓雞蛋進階

二分優化

#include <iostream> #include<bits/stdc++.h> using namespace std; struct aa{int k;int n;}; map<aa,int>dic; int dic2[1000][1000]={0}; int dp(int k,int n){if(k==1){return n;}if(n==0){return 0;}if(dic2[k][n]!=0){return dic2[k][n];}int res=10000;int lo,hi,mid;lo=1;hi=n;///二分法查找while(lo<=hi){mid=(lo+hi)/2;int broken=dp(k-1,mid-1);int un_broken=dp(k,n-mid);if(broken>un_broken){hi=mid-1;res= min(res,broken+1);///res仍需要不斷更新(要最小)continue;}if(broken<un_broken){lo=mid+1;res=min(res,un_broken+1);continue;}if(broken==un_broken){///這里可認為恰好找到了,直接回,而且直接在上面隨便一個加等號也可以res=min(res,broken+1);dic2[k][n]=res;return res;}}dic2[k][n]=res; ///應該寫在循環外面return res; } int main() {int k=2,n=100;cout<<dp(k,n);return 0; }

2020.9.10重寫了一個,上次的代碼全有return,浪費了,又寫出了個bug(應該是最壞情況(v2)),標好了
(v2里沒用min,原代碼用了,咋說,也沒出問題,)
v1

#include <iostream> #include<bits/stdc++.h> using namespace std; int dp[105][105]={0}; int finder(int k,int n){/k:jidanshu n:loucengshuif(dp[k][n]!=0){return dp[k][n];} if(n==0)return 0; if(k==1)return n;int res=10000; int le,ri,mid,sui,wei_sui; zuo:suile you:meisui le=1; ri=n; while(le<=ri) {mid=(le+ri)/2;sui=finder(k-1,mid-1);wei_sui=finder(k,n-mid);///zuididianif(sui<wei_sui){///(zuo)le=mid+1;res=min(res,wei_sui+1);continue;}if(sui>wei_sui){ri=mid-1;res=min(res,sui+1);continue;}if(sui==wei_sui){printf("yes");res=min(res,sui+1);break;} } dp[k][n]=res; return res; } int main() {cout<<finder(2,100);return 0; }

2020.9.10v2

#include <iostream> #include<bits/stdc++.h> using namespace std; int dp[105][105]={0}; int finder(int k,int n){/k:jidanshu n:loucengshuif(dp[k][n]!=0){return dp[k][n];} if(n==0)return 0; if(k==1)return n;int res=10000; int le,ri,mid,sui,wei_sui; zuo:suile you:meisui le=1; ri=n; while(le<=ri) {mid=(le+ri)/2;sui=finder(k-1,mid-1);wei_sui=finder(k,n-mid);///zuididianif(sui<wei_sui){///(zuo)le=mid+1;res=wei_sui+1;///這里要選大的那一個continue;}if(sui>wei_sui){ri=mid-1;res=sui+1;///這里要選大的那一個continue;}if(sui==wei_sui){printf("yes");res=sui+1;break;} } dp[k][n]=res; return res; } int main() {cout<<finder(2,100);return 0; }

重定義狀態轉移(我感覺上次應該是忘寫了)

#include <iostream> #include<bits/stdc++.h> using namespace std; struct aa{int k;int n;}; map<aa,int>dic; int dic2[1000][1000]={0}; int dp(int k,int n){if(k==1){return n;}if(n==0){return 0;}if(dic2[k][n]!=0){return dic2[k][n];}int res=10000;int lo,hi,mid;lo=1;hi=n;///二分法查找while(lo<=hi){mid=(lo+hi)/2;int broken=dp(k-1,mid-1);int un_broken=dp(k,n-mid);if(broken>un_broken){hi=mid-1;res= min(res,broken+1);///res仍需要不斷更新(要最小)continue;}if(broken<un_broken){lo=mid+1;res=min(res,un_broken+1);continue;}if(broken==un_broken){///這里可認為恰好找到了,直接回,而且直接在上面隨便一個加等號也可以res=min(res,broken+1);dic2[k][n]=res;return res;}}dic2[k][n]=res; ///應該寫在循環外面return res; } int main() {int k=2,n=100;cout<<dp(k,n);return 0; }

2020.9.10更新·

#include <iostream> #include<bits/stdc++.h> using namespace std; int dp[105][105]={0}; int finder(int k,int n){/k:jidanshu n:loucengshu int m=0;while(dp[k][m]<n){m++;for(int kk=1;kk<=k;kk++){dp[kk][m]=dp[kk][m-1]+dp[kk-1][m-1]+1;} }return m;} int main() {int k,n;cin>>k>>n;cout<<finder(k,n);return 0; }

總結

以上是生活随笔為你收集整理的高楼扔鸡蛋的全部內容,希望文章能夠幫你解決所遇到的問題。

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