【SCAU 10新生赛】9515 终极BOSS 01背包 dp

Description
Dragon123是某游戏的高级玩家,经常轻松秒杀游戏的终极boss。
游戏公司得知这个消息后十分不服气,决定对游戏里面的终极boss进行一下改造,使dragon123在游戏中有可能永远不能够消灭它。
一开始,终极boss有n滴血。Dragon123有opt种武器,每种武器都能够对该终极boss造成Ki滴血的伤害。
但是,游戏公司偷偷作了一个小小的修改:他们设定了f个数值:R1, R2…Ri。
每当终极boss的血恰好降至这些值的时候,boss的血会自动增加一个固定值M。当boss的血降到0或小于0的时候,boss就挂掉了。
幸好dragon123通过反编译,把游戏公司这些卑鄙的伎俩全部试穿了。
我们假设,在游戏中,dragon123使用武器是没有任何规律的。
所以当dragon123知道这些数值后,他想知道在游戏中玩家是否有可能无法消灭最终boss。

输入格式
输入文件的第一行是4个数字:n,opt,f与M。(n<=2500; opt, f <= 50; M<=100)
接下来有opt行,每行都有一个数字Ki,代表dragon123的武器能够造成的伤害。
接下来有f行,每行都有一个数字Ri,表示当终极boss的血达到这些值的时候,会自动增加M。

输出格式
输出只有一个数字。如果dragon123有可能在游戏中永远不能够消灭最终boss,那么就输出1。否则输出0。

输入样例
Sample Input #1:
10 1 1 5
1
5

Sample Input #2:
10 2 2 1
3
5
4
2

Sample Input #3:
10 2 1 1
10
1
5

输出样例
Sample Output #1:
1

Sample Output #2:
0

Sample Output #3:
1

题意:怪物有n点血量,你有m个武器,每个都能造成一定伤害,有f个设定,怪兽每到达f[i]血量会加d点血,问有没有可能一直打不死。

思路:

标签说是图论,但好像一个dp就过了:
1.首先确定怪兽死不掉的情况就是,你打到r[i]的血量后,它加m,然后你又能把加回来的血打回去,又遇到r[i],就反复横跳了。
2.那么问题就变成了每个r[i]能不能被凑到,且m这个恒定值能不能被凑到(因为你还要把加回来的打回去),这就是一个01背包问题了。
3.用dp[i]表示i能不能恰好达到i这么多的血量。状态转移方程:
if(dp[j - a[i]]) dp[j] = 1;

AC代码:

#include<iostream>
#include<string>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<map>
#include <queue>
#include<sstream>
#include <stack>
#include <set>
#include <bitset>
#include<vector>
#define FAST ios::sync_with_stdio(false)
#define abs(a) ((a)>=0?(a):-(a))
#define sz(x) ((int)(x).size())
#define all(x) (x).begin(),(x).end()
#define mem(a,b) memset(a,b,sizeof(a))
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define rep(i,a,n) for(int i=a;i<=n;++i)
#define per(i,n,a) for(int i=n;i>=a;--i)
#define pb push_back
#define mp make_pair
#define fi first
#define se second
using namespace std;
typedef long long ll;
typedef pair<ll,ll> PII;
const int maxn = 1e5+200;
const int inf=0x3f3f3f3f;
const double eps = 1e-7;
const double pi=acos(-1.0);
const int mod = 1e9+7;
inline int lowbit(int x){return x&(-x);}
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
void ex_gcd(ll a,ll b,ll &d,ll &x,ll &y){if(!b){d=a,x=1,y=0;}else{ex_gcd(b,a%b,d,y,x);y-=x*(a/b);}}//x=(x%(b/d)+(b/d))%(b/d);
inline ll qpow(ll a,ll b,ll MOD=mod){ll res=1;a%=MOD;while(b>0){if(b&1)res=res*a%MOD;a=a*a%MOD;b>>=1;}return res;}
inline ll inv(ll x,ll p){return qpow(x,p-2,p);}
inline ll Jos(ll n,ll k,ll s=1){ll res=0;rep(i,1,n+1) res=(res+k)%i;return (res+s)%n;}
inline ll read(){ ll f = 1; ll x = 0;char ch = getchar();while(ch>'9'||ch<'0') {if(ch=='-') f=-1; ch = getchar();}while(ch>='0'&&ch<='9') x = (x<<3) + (x<<1) + ch - '0',  ch = getchar();return x*f; }
int dir[4][2] = { {1,0}, {-1,0},{0,1},{0,-1} };

bool dp[5005];
ll a[5005], r[5005];

int main()
{
    ll n = read(), m = read(), f = read(), d = read();
    rep(i,1,m) a[i] = read(); rep(i,1,f) r[i] = read();
    dp[0] = 1;
    rep(i,1,m) rep(j,a[i],max(n,d) + d) if(dp[j - a[i]]) dp[j] = 1;
    int flag = 1;
    rep(i,1,f) if(dp[n - r[i]]&&dp[d]) flag = 0;
    cout<<!flag<<endl;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_45492531/article/details/107775003