1. 程式人生 > >【暴力搜尋】【動態規劃】[NOIP 1999]郵票面值設計

【暴力搜尋】【動態規劃】[NOIP 1999]郵票面值設計

其實就是列舉每一個郵票的面值記得保持嚴格遞增,然後DP判斷每一次最多能夠湊出1-哪個面值的郵票,然後下限顯然就是前面一張郵票的面值+1,上限是當前能夠湊出的郵票的面值+1因為顯然如果當前最大為n那麼如果這張面值為n+2那麼顯然n+1不能由原來的組合構成(原來只能弄出n)那麼現在新加入了一個只會變得n+2>n+1那麼顯然n+1永遠湊不出來,那麼顯然同理不能選擇大於n+1的所有數字當作上限。關於DP就是個揹包,自己推一下吧。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
using namespace std; #define MAXK 200 #define MAXN 50 #define MAXEND 10000 #define INF 0x7f7f7f7f int K,N,F[MAXEND+10],Max; vector<int> save; vector<int> w; int ret; int dp(int E, int n){ memset(F, INF, sizeof F); F[0] = 0; for(int V=1; V<=E; V++){ for(int i=1; i<=n;i++){ if
(V - w[i] < 0) break; F[V] = min(F[V], F[V-w[i]] + 1); } } ret = 1; while(F[ret] <= K) ret++; return ret-1; } int length; void dfs(int u){ if(u > N){ length = dp(w[N]*K, u-1); if(length>Max){ Max = length; save = w; } return
; } for(w[u]=dp(w[u-1]*K, u-1)+1;w[u]>w[u-1];w[u]--) dfs(u+1); } void solve(){ w[1] = 1; dfs(2); printf("%d",save[1]); for(int i=2;i<=N;i++) printf(" %d",save[i]); printf("\nMAX=%d\n",Max); } int main() { scanf("%d %d",&K,&N); for(int i=0;i<=N;i++){ save.push_back(0); w.push_back(0); } solve(); return 0; }