Problem I. Spell Boost HDU - 6508 | 有顺序的背包dp

又是烧脑的背包dp,永远也理解不了的背包dp,哎。
待更:为什么要按照w排序????????????!!

题意:
给一些卡,分为四种卡。
1.白卡(没效果)
2.魔法,作用卡(会对作用卡的费用减少,也会被魔法卡作用)
3.作用卡(会被魔法卡作用使其费用减少)
4.魔法卡(会对作用卡的费用减少)
分析:
https://www.cnblogs.com/SSummerZzz/p/11163795.html
先附上别人的题解,由于没有看懂,所以待补吧
代码:
别人的代码

#include<iostream>
#include<algorithm>
using namespace std;
#define rep(i,j,k) for(int i = (j); i <= (k); i++)
#define per(i,j,k) for(int i = (j); i >= (k); i--)

const int N = 510;
int dp[N][N];

struct node{
    int w, x;
    int is_m, is_s;

    bool friend operator < (node a, node b){
        if (a.is_m != b.is_m) return a.is_m > b.is_m;//魔法卡先返回
        else if (a.is_s != b.is_s) return a.is_s < b.is_s;//作用卡越晚用越好

        return a.w < b.w;//先用费用小的,使其dp可以得到全部可能
    }
};

node arr[N];

void init(int x){
//    rep(i, 0, x)rep(j, 0, x) dp[i][j] = 0;
    memset(dp, 0, sizeof(dp));
}

int main(){

    ios::sync_with_stdio(false);
    cin.tie(0);

    int n, W;
    while (cin >> n >> W){
        int m_num = 0;
        rep(i, 1, n){
            cin >> arr[i].w >> arr[i].x >> arr[i].is_m >> arr[i].is_s;
            if (arr[i].is_m) ++m_num;//统计魔法卡数量
        }
        init(n);
        sort(arr + 1, arr + 1 + n);
        bool is_s = false;//判断是不是作用卡
        //从大到小遍历,可以不影响之前的状态
        rep(i, 1, n){
            if (arr[i].is_m){
                per(k, i, 1){//魔法卡从多到少
                    per(j, W, 0){//费用从多到少

                        int tmp_w = 0;
                        if (arr[i].is_s){//有被作用效果
                            is_s = true;
                            tmp_w = max(0, arr[i].w - (k - 1));//触发魔法卡效果
                        }
                        //对于k张魔法卡,之前只有k-1张魔法卡,假如一张魔法卡去更新dp,所以被作用时
                        //应该是魔法卡数量-1的费用减少
                        if (is_s && tmp_w <= j){//是作用卡,费用足够
                            dp[j][k] = max(dp[j][k],dp[j - tmp_w][k - 1] + arr[i].x);
                        }
                        else if (!is_s && arr[i].w <= j){//不是作用卡,费用足够
                            dp[j][k] = max(dp[j][k], dp[j - arr[i].w][k - 1] + arr[i].x);
                        }
                    }
                }
            }
            else {
                //进入该部分时,全部的魔法卡使用情况已经存入dp,之后的都不是魔法卡
                per(k, m_num, 0){//m_num是魔法卡总数量,可能有不用魔法卡才能的到最大攻击的情况
                    per(j, W, 0){     
                        int tmp_w = 0;
                        if (arr[i].is_s){
                            is_s = true;
                            tmp_w = max(0, arr[i].w - k);
                        }
                        //对于k张魔法卡,被作用卡卡费用减少k
                        if (is_s && tmp_w <= j){
                            dp[j][k] = max(dp[j][k], dp[j - tmp_w][k] + arr[i].x);
                        }
                        else if (!is_s && arr[i].w <= j){
                            dp[j][k] = max(dp[j][k], dp[j - arr[i].w][k] + arr[i].x);
                        }
                    }
                }
            }
            is_s = false;
        }
        int ans = 0;
        rep(i, 0, m_num) ans = max(ans, dp[W][i]);//遍历费用是W的dp最大值,即为最大攻击力
        cout << ans << endl;
    }
    return 0;
}