894 div3 e (背包

#include 
#define int_max 0x3f3f3f3f;
#define long_max 9223372036854775807;
using namespace std;
using VI = vector;
typedef long long ll;
typedef pair PII;
typedef pair PDD;
typedef unsigned long long ull;
const int MAXN = 1e6;
int s[110];
void solve(){
    int w,f,n;
    cin>>w>>f>>n;
    int sum = 0;
    for(int i=1;i<=n;i++){
        cin>>s[i];
        sum += s[i];
    }
    VI dp(sum+1,0);
    dp[0] = 1;
    for(int i=1;i<=n;i++){
        for(int j=sum;j>=s[i];j--){
            if(dp[j - s[i]]) dp[j] = 1;
        }
    }

    int res = 1e9 ;
    for(int i=0;i<=sum;i++){
        if(dp[i]){
            //cout<>t;
    while(t--){
        solve();
    }
}

考虑将怪物分成俩个集合  x, y   其实 x + y = sum;

那么枚举出来 子集 x    y 就是sum - x

考虑 x 用 w 消灭, y 用 f  消灭    (对称的,会有反过来的情况)

那么就把问题变成了枚举sum的所有子集

01背包问题  前n个物品,容量为j 是为可以达到

因为只有0 1,俩种价值,表示能否达到,可以用bitset优化

bitset 的本质就是一个特别长的二进制数字,可以进行各种位运算操作

如果000000111 

那么001110111 左移加上 | 运算

#include 
#define int_max 0x3f3f3f3f;
#define long_max 9223372036854775807;
using namespace std;
using VI = vector;
typedef long long ll;
typedef pair PII;
typedef pair PDD;
typedef unsigned long long ull;
const int MAXN = 1e6;
int s[110];
void solve(){
    int w,f,n;
    cin>>w>>f>>n;
    int sum = 0;
    for(int i=1;i<=n;i++){
        cin>>s[i];
        sum += s[i];
    }
    //VI dp(sum+1,0);
    bitset<1000010>dp;
    dp[0] = 1;
    for(int i=1;i<=n;i++){
       dp |= dp << s[i];
    }

    int res = 1e9 ;
    for(int i=0;i<=sum;i++){
        if(dp[i]){
            //cout<>t;
    while(t--){
        solve();
    }
}

你可能感兴趣的:(dp,思维构造,算法,数据结构)