zoukankan      html  css  js  c++  java
  • dp

    题意:

            给你 n 张卡片,总共可以消耗的法力值,求最多可以造成多少伤害, 卡片分为2种,一种是魔法卡,使用后可以使所有的连环卡的费用全部减1,另一种是连环卡,因魔法卡的使用可以使其费用减1,问最终最多可以造成多少的伤害

    思路分析 :

          比赛的时候大脑短路了,基本不愿意去想东西了,导致题目没有出来,这个题就是一个 01背包,但是增加了一个限制条件,所以我们多增加一维表示到当前位置,所使用的魔法卡的数量,但是呢,还有一个很关键的地方,就是我们要先对卡片经行一个排序的预处理,这样在搞 dp的时候,才不会对后续有任何的影响,排序的时候,优先使用魔法卡,然后两者都是的卡,剩下的卡就随意了。

    代码示例:(未测试)

    #define ll long long
    const int maxn = 1e6+5;
    const int mod = 1e9+7;
    const double eps = 1e-9;
    const double pi = acos(-1.0);
    const int inf = 0x3f3f3f3f;
    
    int n, w;
    
    struct node
    {
        int w, x, p1, p2;
        
    }pre[505];
    int dp[505][505][505];
    int cnt = 0;
    
    bool cmp1(node a, node b){
        if (a.p1 == b.p1) return a.p2 < b.p2;
        return a.p1 > b.p1;
    }
    
    bool cmp2(node a, node b){
        if (a.w == b.w) return a.x > b.x;
        return a.w < b.w;    
    }
    
    void fun(){
        
        for(int i = 1; i <= n; i++){
            for(int j = 1; j <= w; j++){
                for(int k = 0; k <= min(i, cnt); k++){ // 使用魔法卡
                    if (pre[i].p1 && !pre[i].p2) { // 1 0
                        if (j >= pre[i].w && k) 
                            dp[i][j][k] = max(dp[i-1][j][k], dp[i-1][j-pre[i].w][k-1]+pre[i].x);
                        else dp[i][j][k] = dp[i-1][j][k]; 
                    }
                    else if (pre[i].p1 && pre[i].p2){ // 1 1
                        int cost = max(pre[i].w-k+1, 0);
                        //if (i == 2 && j == 2) printf("cost = %d
    ", cost);
                        if (j >= cost && k){
                            dp[i][j][k] = max(dp[i-1][j][k], dp[i-1][j-cost][k-1]+pre[i].x);
                        }
                        else dp[i][j][k] = dp[i-1][j][k];             
                    }
                    else if (!pre[i].p1 && pre[i].p2){ // 0 1
                        int cost = max(pre[i].w-k, 0);
                        if (j >= cost && k){
                            dp[i][j][k] = max(dp[i-1][j][k], dp[i-1][j-cost][k]+pre[i].x);
                        }
                        else dp[i][j][k] = dp[i-1][j][k];
                    }
                    else { // 0 0
                        if (j >= pre[i].w){
                            dp[i][j][k] = max(dp[i-1][j][k], dp[i-1][j-pre[i].w][k]+pre[i].x); 
                        }
                        else dp[i][j][k] = dp[i-1][j][k];
                    }
                    //printf("+++%d %d %d =  %d  
    ",i, j, k, dp[i][j][k]);
                }        
            }
        }
    }
    
    void init(){
        int pos1 = -1, pos2 = -1;
        
        for(int i = 1; i <= n; i++){
            if (pre[i].p1 && !pre[i].p2) {
                pos1 = i;
                break;
            }
        }
        for(int i = n; i >= 1; i--){
            if (pre[i].p1 && !pre[i].p2) {
                pos2 = i;
                break;
            }
        }
        if (pos1 != -1) sort(pre+pos1, pre+pos2+1, cmp2);
        
        pos1 = pos2 = -1;
        for(int i = 1; i <= n; i++){
            if (pre[i].p1 && pre[i].p2) {
                pos1 = i;
                break;
            }
        }
        for(int i = n; i >= 1; i--){
            if (pre[i].p1 && pre[i].p2) {
                pos2 = i;
                break;
            }
        }
        if (pos1 != -1) sort(pre+pos1, pre+pos2+1, cmp2);
        
        pos1 = pos2 = -1;
        for(int i = 1; i <= n; i++){
            if (!pre[i].p1 && !pre[i].p2) {
                pos1 = i;
                break;
            }
        }
        for(int i = n; i >= 1; i--){
            if (!pre[i].p1 && !pre[i].p2) {
                pos2 = i;
                break;
            }
        }
        if (pos1 != -1) sort(pre+pos1, pre+pos2+1, cmp2);
        
        pos1 = pos2 = -1;
        for(int i = 1; i <= n; i++){
            if (!pre[i].p1 && pre[i].p2) {
                pos1 = i;
                break;
            }
        }
        for(int i = n; i >= 1; i--){
            if (!pre[i].p1 && pre[i].p2) {
                pos2 = i;
                break;
            }
        }
        if (pos1 != -1) sort(pre+pos1, pre+pos2+1, cmp2);
    }
    
    int main() {
        //freopen("in.txt", "r", stdin);
        //freopen("out.txt", "w", stdout);
        
        cin >> n >> w;
        for(int i = 1; i <= n; i++){
            scanf("%d%d%d%d", &pre[i].w, &pre[i].x, &pre[i].p1, &pre[i].p2);
            if (pre[i].p1 == 1) cnt++;
        }
        sort(pre+1, pre+1+n, cmp1);
        init(); 
        for(int i = 1; i <= n; i++){
            printf("%d%d%d%d
    ", pre[i].w, pre[i].x, pre[i].p1, pre[i].p2);
        }
        memset(dp, 0x8f, sizeof(dp)); 
        for(int j = 0; j <= w; j++) {
            dp[0][j][0] = 0;
        }
        fun();
        int ans = 0;
        for(int i = 0; i <= cnt; i++) ans = max(ans, dp[n][w][i]);
        printf("%d
    ", ans);    
        return 0;
    }
    /*
    4 3
    1 3 0 1
    1 0 0 0
    3 3 1 1
    3 4 1 0
    
    3 3
    3 3 1 1
    2 3 1 1
    1 3 1 1
    
    3 4
    3 10 1 1
    30 400 1 1
    4 200 1 1
    
    5 5
    6 50 1 1
    3 30 0 1
    3 3 1 0
    3 200 0 0
    3 6 1 0
    
    6 4
    1 3 1 0
    2 5 0 0
    1 2 0 1
    2 2 1 1
    3 4 0 1
    1 1 1 0
    */
    
    东北日出西边雨 道是无情却有情
  • 相关阅读:
    Navicat Preminm12 连接Oracle数据库失败或闪退
    kafka tool报错:Error fetching datea.Offset out of range
    kafka修改默认端口号
    post发送请求,body格式
    一、线程基础、线程之间的共享和协作(1)
    jQuery(三) 动画操作一
    jQuery(二) 选择器
    jQuery(一)
    javascript面向过程与面向对象
    鼠标跟随动画: event
  • 原文地址:https://www.cnblogs.com/ccut-ry/p/9121110.html
Copyright © 2011-2022 走看看