Codeforces Round #171 (Div. 2)
D:状态DP,DP[S]表示到达S状态需要的最少的箱子数,有一个关键的条件是,A序列中的数是一个一个一次产生的,所以怎么转移就知道了
int dfs(int flag) { if(dp[flag]!=-1) return dp[flag]; if(flag == 1) return dp[flag] = 1; int ans = inf; int bits = __builtin_popcount(flag); revp(i,n-1,0) { if(flag & two(i)) { int to = (flag ^ two(i)) | two(i-1) ; //去掉当前i这个数,加上i-1的状态,因为上一个产生的数一定是i-1 REP(j,i) REP(k,j+1) { if(a[i] == a[j] + a[k]) { int tmp = dfs(to | two(j) | two(k)); //如果第i个数由第j 和 第k两个数组成,那么上一次操作的时候这两个数必须要在 if(tmp!=inf)ans = min(ans,max(tmp,bits)); } } break; } } dp[flag] = ans; return ans;}int main() { cin >> n; REP(i,n) cin>>a[i]; memset(dp,-1,sizeof(dp)); int ans = dfs(two(n-1)); if(ans == inf) puts("-1"); else printf("%d\n",ans); return 0;}
E:贪心,从右往左碰上连续L个1,就可以使总的个数减少L-2(L>=2)