1. 程式人生 > >2017-2018 ACM-ICPC Pacific Northwest Regional Contest (Div. 1) B - Enlarging Enthusiasm dp好題

2017-2018 ACM-ICPC Pacific Northwest Regional Contest (Div. 1) B - Enlarging Enthusiasm dp好題

B - Enlarging Enthusiasm

感覺做到過好多的dp題都會和單調性結合在一起。

思路:dp[ s ][ pre ][ res ] 表示的是已選擇了s,上一個是pre, 還有res 的分數的方案數。

然後再列舉下一個位置的時候,把其他位置的也減去這個值,因為是單調遞增的所以不會多減,

這樣就能保證pre 和 當前要列舉的 i 位置的差值永遠為 a[ pre ] - a[ i ]

#include<bits/stdc++.h>
#define LL long long
#define fi first
#define se second
#define
mk make_pair #define PLL pair<LL, LL> #define PLI pair<LL, int> #define PII pair<int, int> #define SZ(x) ((int)x.size()) #define ull unsigned long long using namespace std; const int N = 1e5 + 7; const int inf = 0x3f3f3f3f; const LL INF = 0x3f3f3f3f3f3f3f3f; const int mod = 1e9 + 7
; const double eps = 1e-8; const double PI = acos(-1); int n, m, ans, mx, a[12], dp[1<<12][12][701], num[1<<12]; int dfs(int s, int pre, int res) { if(res < 0) return 0; if(s+1 == 1<<n) return 1; if(~dp[s][pre][res]) return dp[s][pre][res]; dp[s][pre][res]
= 0; for(int i = 0; i < n; i++) if(!(s>>i&1)) dp[s][pre][res] += dfs(s|1<<i, i, res-max(a[pre]-a[i]+1, 0)*(n-num[s])); return dp[s][pre][res]; } int main() { memset(dp, -1, sizeof(dp)); scanf("%d%d", &n, &m); for(int i = 0; i < n; i++) { scanf("%d", &a[i]); mx = max(mx, a[i]); } for(int i = 1; i < (1<<n); i++) num[i] = num[i-(i&-i)] + 1; for(int i = 0; i < n; i++) if(a[i] != mx) ans += dfs(1<<i, i, m-(mx-a[i]+1)*n); printf("%d\n", ans); return 0; } /* */