高楼扔鸡蛋
動態規劃:高樓扔雞蛋:
文章目錄
- 高樓雞蛋進階
- 二分優化
- 重定義狀態轉移(我感覺上次應該是忘寫了)
題目:
*你面前有一棟從 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
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; }總結
- 上一篇: spring中的Filter使用
- 下一篇: Maven-生命周期