zoukankan      html  css  js  c++  java
  • 试题 算法提高 进攻策略加强(dp、模拟)

    问题描述
      植物大战僵尸这款游戏中,还有一个特别的玩儿法:玩家操纵僵尸进攻植物。
      首先,僵尸有m种(每种僵尸都是无限多的),玩家可以选择合适的僵尸来进攻。使用第i种僵尸需要花费Wi资源,可以得到Pi的攻击效果。在这里,我们认为多个僵尸总的攻击效果就是他们每个攻击效果的代数和。
      地图共有n行,对于第i行,最左端有若干植物,这些植物需要至少Qi的攻击才能被全部消灭。若一行上的植物全部被消灭,我们称这一行被攻破。
      由于资源紧张,你只有总量为K的资源,不一定能够攻破所有行。但统治者希望攻破相邻的T行,并希望T尽量的大。你能帮他算出T的值吗?
    输入格式
      第一行三个非负整数:m、n、K;
      第二行m个正整数,第i个数表示Wi;
      第三行m个正整数,第i个数表示Pi;
      第四行n个非负整数,第i个数表示Qi。
    样例输入

    3 11 39
    5 2 11
    3 1 7
    5 3 6 10 3 2 4 200 1 1 1

    样例输出
    4
    数据规模和约定
    对于70%的数据:n<=1000
    对于100%的数据:n<=200000,m<=100,K<=1000000,所有Pi、Qi<=100000000
    思路
    有点背包的感觉,思路是参考网上的,先记录植物的最大防御值,再通过dp得到1-最大防御值所消耗的最小资源数。
    再从左往右依次遍历记录最大值。
    #include<bits/stdc++.h>
    using namespace std;
    int w[200005];///选择i类僵尸的消耗资源数
    int p[200005];///选择i类僵尸的攻击值
    int q[200005];///i行植物的防御力
    int dp[200005];///枚举1-植物防御最大值,每个防御值所需的最少资源
    int maxx,maxn;
    /*
    3 11 39
    5 2 11
    3 1 7
    5 3 6 10 3 2 4 200 1 1 1
    */
    int main(){
        int m,n,k;
        scanf("%d%d%d",&m,&n,&k);
        for(int i=0;i<m;i++){
            scanf("%d",&w[i]);
        }
        for(int i=0;i<m;i++){
            scanf("%d",&p[i]);
        }
        for(int i=0;i<n;i++){
            scanf("%d",&q[i]);
            maxx=max(maxx,q[i]);
        }
        dp[0]=0;///防御值为0时消耗资源数为0
        for(int i=0;i<m;i++){
            for(int j=1;j<=maxx;j++){
                if(i==0){///只有1类僵尸时
                    if(j<=p[i]){///防御值小于此攻击值
                        dp[j]=w[i];
                    }
                    else{///防御值大于此攻击值
                        dp[j]=dp[j-p[i]]+w[i];
                    }
                }
                else{
                    if(j<=p[i]){
                        dp[j]=min(dp[j],w[i]);
                    }
                    else{
                        dp[j]=min(dp[j],dp[j-p[i]]+w[i]);
                    }
                }
            }
        }
            int num,cost;
            for(int i=0;i<n;i++){///以i植物为左端枚举
                    num=0;///攻破的行数
                    cost=k;
                    int j=i;
                    while(cost&&j<n){
                        cost-=dp[q[j]];
                        num++;
                        j++;
                    }
                    maxn=max(maxn,num);
                    if(maxn>n-i)break;///当前最大行数大于剩余的区间长度的话直接退出
            
            cout<<maxn<<endl;
            return 0;
    }
  • 相关阅读:
    声音走样
    Terrain
    输出循环小数
    解决代码中多余的空行
    与二进制有关的几道面试题
    反转一个整数
    DirectX常见编译错误及解决办法
    STLset
    Visual Studio Autoexpand Information for DirectX 9
    素数环谈代码优化
  • 原文地址:https://www.cnblogs.com/mohari/p/13556800.html
Copyright © 2011-2022 走看看