1. 程式人生 > 實用技巧 >acwing-168-生日蛋糕(剪枝+深搜)+codeforces-661-div3-D

acwing-168-生日蛋糕(剪枝+深搜)+codeforces-661-div3-D

acwing-168-生日蛋糕(剪枝)

題意:給定m層蛋糕的最大體積n,如何使表面積最小

解:暴搜,順序即為按從下到上的蛋糕層數,或者從上到下的蛋糕層數

剪枝:

1,優化搜尋順序,所以就從下到上進行搜尋。

每一層列舉高度和半徑,按照遞減順序來列舉。塊數約大,決策越少;

dfs狀態,當前列舉到哪一層,當前的體積,當前的面積(r,和h有範圍)dfs(dep,v,s);

2,r,h從大到小列舉。

當前體積為v,則剩下體積n-v

表面積(此題可以忽略π),r*r*h,h=1,r最大,r最大√n-v,r有限制,

每次r的值 depth<=r<=min(√n-v,R[depth+1]-1)

每次h的值 depth<=h<=min( (n-v)/r^2 , H[depth+1] -1)(n-v)/r^2向下取整

3,dep層的minv(dep)+v>n直接return掉。

或者mins(dep)+s>ans,直接return。

minv和mins直接取極限

4,n-v=∑i=1,dep (ri^2*hi)

Sdep=∑i=1,dep(2*ri*hi)

=2/r(dep+1)* ∑ri*hi*r(dep+1)>=2/r(dep+1)*∑ri*ri*hi=2(n-v)/r(dep+1)

則當前Sdep>=2(n-v)/r(dep+1)

即s+sdep>=ans,直接return。

程式碼:

#include<bits/stdc++.h>
const int maxn=30;
const int inf=0x3f3f3f3f;
typedef long long ll;
using namespace std;

int n,m;
int minv[maxn],mins[maxn];
int R[maxn],H[maxn];
int ans=inf;

void dfs(int dep,int v,int s)
{
    if(v+minv[dep]>n) return ;
    if(s+mins[dep]>=ans) return
; if(s+2*(n-v)/R[dep+1]>=ans) return ;//3個剪枝 if(!dep)//搜尋到最後一層 { if(v==n) ans=s; return ; } for(int i=min(R[dep+1]-1,(int)sqrt(n-v)); i>=dep; i--)//從當前限制開始進行列舉 { for(int j=min(H[dep+1]-1,(n-v)/i/i); j>=dep; j--) { int t=0; if(dep==m) t=i*i;//最後一層,加上圓的面積 R[dep]=i; H[dep]=j;//每次更新,為0時會出現錯誤 dfs(dep-1, v+i*i*j,s+2*i*j+t);//繼續搜尋 } } } int main() { cin>>n>>m; for(int i=1; i<=m; i++)//初始化v和s,極限化,第一層1,第二層2... { minv[i]=minv[i-1]+i*i*i; mins[i]=mins[i-1]+2*i*i; } R[m+1]=H[m+1]=inf; dfs(m,0,0); if(ans==inf) ans=0; cout<<ans<<endl; return 0; }

codeforces-661-div3-D

題意:01串,找最小子序列使得01間隔開來

解:棧模擬,對於每一個序列,記錄下最後一個1和0的位置,然後對於第i個位置,如果是0,就和上一個1同序列,如果是1就和上一個0同序列;

棧模擬,時間複雜度O(N);

程式碼:

#include<bits/stdc++.h> constintmaxn=30; constintinf=0x3f3f3f3f; typedeflonglongll; usingnamespacestd;
intt;
voidsolve() { intn; cin>>n; strings; cin>>s; stack<int>st1,st2;//st1存0,st2存1 vector<int>ans(n,0); intma=0; for(inti=0;i<n;i++) { if(s[i]=='0')//當前為0 { if(!st2.empty())//存1的棧不為空 { ans[i]=ans[st2.top()];//尋找上個1的位置 st2.pop(); st1.push(i); } else { ans[i]=st1.size()+1; st1.push(i); } } else { if(!st1.empty()) { ans[i]=ans[st1.top()]; st1.pop(); st2.push(i); } else { ans[i]=st2.size()+1; st2.push(i); } } ma=max(ma,ans[i]); } cout<<ma<<endl; cout<<ans[0]; for(inti=1;i<n;i++)cout<<""<<ans[i]; cout<<endl; } intmain() { cin>>t; while(t--) solve(); system("pause"); return0; }