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