洛谷 P1441 砝碼稱重(DFS回溯 DP)

2021-09-27 06:10:19 字數 1207 閱讀 6927

題目大意:

已知有n個砝碼,我們從中可以任意去掉m個,問我們最多可以得到多少種不同的重量。

解題思路:

首先,我們把解題分為兩個思路:首先,我們看任意去掉m個。

這個我們可以用dfs模擬,關鍵在於停止條件。我們知道我們每一步都可以選擇新增或者不新增某個砝碼,然後重複n次。

這樣我們就有最簡單的遞迴停止條件,遞迴到第n次我們開始可以看看刪除的數目是多少,若是m,我們就進入下一步。但顯然,我們發現,其實若遞迴過程中刪除的數目大於m,我們其實是可以停止遞迴的。

得到哪些砝碼需要後,我們進入下一步計數,統計有多少種不同重量。

我們設立狀態memo[i][j],表示若我們遍歷到第j個重量為i是否可行,可行memo[i][j]=1,若不可行我們把memo[i][j]=0.

這裡轉移首先:若

memo[i][j-1]=1,那麼memo[i][j]=1

若memo[i][j-1]=0,是不是代表memo[i][j]=0呢?

不一定,我們假設砝碼數列為a1 a2 a3 ...

假設若memo[i-ai][j-1]=1則memo[i][j]=1

注意i的列舉範圍,0<=i<=sum+a[i]

其中sum為前面i-1個的數列求和。

廢話:提高組的題目是越來越難了,現在題目往往是將幾個演算法結合起來考,所以我們不應該只用單一演算法去解了。

另外這裡的dp也很有意思,我們發現狀態這裡的設定有點像01dp,【第幾個】【重量】,只不過這裡的取值只有0或者1兩種可能。

另外dfs回溯的時候,一般是需要有乙個狀態去記錄我們走去了第幾層。

#include using namespace std;

const int maxn =25;

int tar[maxn];

int ans;

int n,m;

int ls;

vectorarrmv;

int f[maxn*100][maxn];

void dp()

}else f[i][j]=f[i][lstep];

if(f[i][j]==0)continue;

if(i!=0 && weight[i]==0)

ans=-1;

//memset(tar,-1,sizeof(tar));

dfs(0,0);

cout

}

洛谷P1441 砝碼稱重

現有n個砝碼,重量分別為 aia iai 在去掉 mmm 個砝碼後,問最多能稱量出多少不同的重量 不包括 000 請注意,砝碼只能放在其中一邊。第 111 行為有兩個整數 nnn 和 mmm,用空格分隔。第 222 行有 nnn 個正整數 a1,a2,a3,ana 1,a 2,a 3,ldots a...

洛谷 P1441 砝碼稱重(深搜 DP)

傳送門 題目描述 現有n個砝碼,重量分別為a1,a2,a3,an,在去掉m個砝碼後,問最多能稱量出多少不同的重量 不包括0 輸入輸出格式 輸入格式 輸入檔案weight.in的第1行為有兩個整數n和m,用空格分隔 第2行有n個正整數a1,a2,a3,an,表示每個砝碼的重量。輸出格式 輸出檔案wei...

洛谷 P1441 砝碼稱重 子集列舉 bitset

題目描述 現有n個砝碼,重量分別為a1,a2,a3,an,在去掉m個砝碼後,問最多能稱量出多少不同的重量 不包括0 請注意,砝碼只能放在其中一邊。輸入格式 輸入檔案weight.in的第1行為有兩個整數n和m,用空格分隔 第2行有n個正整數a1,a2,a3,an,表示每個砝碼的重量。輸出格式 輸出檔...