您的位置:首页 > 其它

[bzoj-5018][Snoi2017]英雄联盟 题解

2017-09-10 17:18 267 查看
题目传送门

题意解析:题目有点像背包,就是给了你n个物品,每个物品有个价格和数量,然后问你在方案数>=m的情况下的最小花费。(方案数是显而易见的每种物品选取的数量之积)

My opinion:题目很明显是一题类似背包的问题,所以当然是 dfs dp了。一开始想到的状态就是f[i][j]表示前i个物品,方案数是j的最小花费,可是这样的话,因为方案数太大,有10^17,先不说MLE,还有TLE。所以我们要换一个状态,我们可以把方案数换成价格,然后存最大的方案数。但是如果我们不节制(不要想歪了),这样方案数还会爆掉long long,然后会发现一个有趣的东西,m是10^17,ki<=10,所以每次如果是m*ki完全不会爆long long,而答案只需要判断答案是否大于等于m,所以每次当方案数大于m时,我们就把方案数改成m。

总结:

1、输入。

2、dp。

3、输出。

……………………实在想不出怎么总结了(dp方程式也特别明显)。

顺推的代码:

#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#define rep(i,a,n) for (int i=a;i<=n;i++)
#define per(i,a,n) for (int i=a;i>=n;i--)
#define Clear(a,x) memset(a,x,sizeof(a))
#define ll long long
#define INF 2000000000
#define eps 1e-8
using namespace std;
ll read(){
ll x=0,f=1;
char ch=getchar();
while (ch<'0'||ch>'9') f=ch=='-'?-1:f,ch=getchar();
while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
return x*f;
}
const int maxn=125,maxcost=250000;
int n;
int num[maxn],c[maxn];
ll f[maxn][maxcost];
ll m;
int main(){
n=read(),m=read();
rep(i,1,n) num[i]=read();
rep(i,1,n) c[i]=read();
int sum=0;
rep(i,1,n)
sum+=num[i]*c[i];
f[0][0]=1;
rep(i,0,n-1)
rep(j,0,sum)
rep(k,0,num[i+1])
f[i+1][j+k*c[i+1]]=min(m,max(f[i+1][j+k*c[i+1]],f[i][j]*(ll)(k==0?1:k)));
rep(i,0,sum)
if (f
[i]>=m){
printf("%d\n",i);
return 0;
}
}


然后这里还有一篇逆推的:

大佬的题解

附上AC记录:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: