洛谷p1077 擺花

2022-02-19 21:05:25 字數 2884 閱讀 7342

題外廢話:

真的超級喜歡這道題

擺花【題目鏈結】

yy一提醒,我發現這道題和【洛谷p2089】 烤雞有異曲同工之妙(資料更大了更容易tle呢qwq)

solution1:(暴搜)

搜尋:關於搜尋就不用多介紹了吧,這裡是用了dfs:dfs函式中有兩個變數,rest和i分別表示還需要擺放多少盆花以及現在擺放到第幾種花了,因為我們是從0開始列舉,因此如果某種花我們不選擇,那就可以看做這種花選擇了0盆;

幾個返回條件:

1.rest==0時,記錄ans++(ans是全域性變數)return,不需要滿足rest==0&&i=n+1(因為只要rest被列舉完了就可以了,後面的花不擺放就好啦)

2.i==n+1時,return;為什麼是i=n+1呢,因為當i=n時,我們並沒有列舉第n種花擺放的盆數,如果現在就返回,顯然是會對結果造成很大的影響,進而影響整個結果;

核心語句:

其實就一句話:

for(int j=0;j<=a[i];j++)

dfs(rest-j,i+1);

直接暴力dfs因為實際並沒有改變rest和i的值,所以我們連回溯都不需回溯;

以下是完整code:

code1:

#includeusing

namespace

std;

intn,m,ans,cnt;

int a[110],b[110

];void dfs(int rest/*

還需要擺多少盆花

*/,int i/*

n種花*/

)

if(i==n+1) return

;

if(rest<0) return

;

for(int j=0;j<=a[i];j++)

dfs(rest-j,i+1

);

return;}

intmain()

但是非常遺憾的是暴搜顯然不是正解,成功的tle了7個點(功成身退)

所以我們想到了記憶化搜尋:

solution2:(記憶化搜尋)

寫暴搜的原因是因為並不會正解dp,因此只好暴搜了,然後又知道暴搜妥妥的tle,所以在暴搜**完成之後,改成了記憶化:

大致思路還是沒有變,但dfs從沒有返回值變成了帶有返回值的dfs,當rest==0時(形成一種擺花條件時)return 1;否則return 0(對於最小子問題);對於每一次定義乙個ans(當然也可以開全域性然後每次重新賦值),列舉所有的擺花盆數,ans+=dfs(rest-j,i+1)[意思是對於某種花列舉所有可能的擺放盆數,統計剩餘的空位置的總方案數,表示某種花擺j盆的總方案數(可能有點不對是非常繞)],記憶化陣列b[i][rest]表示第i種花擺放前剩餘rest個空位置(沒有擺花)剩餘rest個位置擺花的方案數,當我們已經計算過這個方案數以後,就可以直接拿來用而不是總是遞迴炸掉了。所以加一句

if(b[i][rest]) return b[i][rest];

如何計算b[i][rest]以及每一步的ans:

其實樓上兩個東西是一回事,b[i][rest]=ans;

下面來看如何計算ans:首先列舉第i種花所有擺放盆數(0~a[i]),然後dfs(rest-j,i+1),不斷將求得的值加到ans裡,(ans記錄的是當前要擺第i種花,此時還剩rest(第i種花還沒擺)個位置時所有擺花的方案數)不要忘記取mod;

最後不要忘記return ans;

code2:

#includeusing

namespace

std;

long

long

n,m,cnt;

long

long a[1100],b[1100][1100

];const

int mod=1000007

;long

long dfs(long

long rest/*

還需要擺多少盆花

*/,long

long i/*

擺放n種花*/)

b[i][rest]=ans;

return

ans;

}int

main()

悄咪咪的粘上記憶化搜尋的模板:(來自oi-wiki)

int

g[maxn];

intf(傳入數值)

intmain()

solution3:(正解-動態規劃)

q姓神仙的題解【題解】

定義二維陣列f[i][j]表示擺放i種花共j盆的最大方案數,初始狀態是:f[i][0]=1;(因為不管是哪種花,只要不擺放,方案數均為1)這裡雖然是二位陣列,但dp時需要三重迴圈第一重迴圈i表示擺放i種花,第二重迴圈j表示這i種花共擺放多少盆(顯然是1~m),第三重迴圈k,表示的是這種花擺放的盆數,(從0盆到a[i]盆),這裡的第三層迴圈要從j到j-a[i]進行列舉轉移方程就是f[i][j]+=f[i-1][k]%mod:

啥意思:

因為前i種花一共擺放j盆,那麼假設第i種花擺放k1(k1∈(0,a[k1])盆,那麼前面的i-1種花就擺放j-k1盆(所以第三層迴圈列舉的是前i-1種花擺放的方案數),那麼所有的方案數相加就是擺放i種花j盆的最大方案數;

最後的答案就是f[n][m]%mod;(最後要%mod防止超出答案)

code3:

#includeusing

namespace

std;

intn,m;

int a[110],f[110][110

];const

int mod=1000007

;int

main()

cout

}

真.end-

擺花 洛谷p1077

小明的花店新開張,為了吸引顧客,他想在花店的門口擺上一排花,共m盆。通過調查顧客的喜好,小明列出了顧客最喜歡的n種花,從1到n標號。為了在門口展出更多種花,規定第i種花不能超過ai盆,擺花時同一種花放在一起,且不同種類的花需按標號的從小到大的順序依次擺列。試程式設計計算,一共有多少種不同的擺花方案。...

洛谷 P1077 擺花

題目原位址 2 4 3 2 輸出 2首先,我們想到的一定是暴力dfs 20分 include include using namespace std int n,m,ans,a 105 b 105 void dfs int k,int space if k n return for int i mi...

洛谷 P1077 擺花

一道簡單的dp問題。dp i j 表示前i種花j個花盆的方案數。那麼就有狀態轉移方程為sum dp i 1 k 其中k的取值是從0到min j,a i include using namespace std int m,n int dp 105 105 int a 105 int mod 10000...