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)