1.普通情况
采药
辰辰是个天资聪颖的孩子,他的梦想是成为世界上最伟大的医师。
为此,他想拜附近最有威望的医师为师。
医师为了判断他的资质,给他出了一个难题。
医师把他带到一个到处都是草药的山洞里对他说:“孩子,这个山洞里有一些不同的草药,采每一株都需要一些时间,每一株也有它自身的价值。我会给你一段时间,在这段时间里,你可以采到一些草药。如果你是一个聪明的孩子,你应该可以让采到的草药的总价值最大。”
如果你是辰辰,你能完成这个任务吗?
输入格式
输入文件的第一行有两个整数 T 和 M,用一个空格隔开,T 代表总共能够用来采药的时间,MM 代表山洞里的草药的数目。
接下来的 M 行每行包括两个在 1 到 100 之间(包括 1 和 100)的整数,分别表示采摘某株草药的时间和这株草药的价值。
输出格式
输出文件包括一行,这一行只包含一个整数,表示在规定的时间内,可以采到的草药的最大总价值。
数据范围
1≤T≤1000,
1≤M≤100
输入样例:
70 3
71 100
69 1
1 2
输出样例:
3
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int t,m,i,j;
ll dp[1005];
ll w[105],v[105];
int main()
{
scanf("%d%d",&t,&m);
for(i=1;i<=m;i++)
{
scanf("%d%d",&w[i],&v[i]);
}
for(int i=1;i<=m;i++)
{
for(int j=t;j>=w[i];j--)
{
dp[j]=max(dp[j],dp[j-w[i]]+v[i]);
}
}
cout<<dp[t]<<endl;
return 0;
}
2.体积大价值小
题目描述
给定 n 个物品,每个物品的价值为 vi,重量为 wi,请从这些物品中选出一些,在它们的重量之和不超过一个给定值 c 的前提下,价值之和达到最大。
注意本题中物品的重量可能比较大。
输入格式
第一行:两个整数 n 与 c。
第二行到第 n+1 行,第 i+1 行有两个整数表示 vi 与 wi
输出格式
单个整数:表示满足限定条件下的最大价值和。
数据范围
- 对于 30% 的数据, n≤20;
- 对于 60% 的数据, c≤10000;
- 对于 100% 的数据, 1≤n≤500,1≤c≤10^18,1≤vi≤500,1≤wi≤10^18。
样例数据
输入:
3 1000
90 900
53 550
38 400
输出:
91
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=510;
int v[N],w[N],n,c;
int sum;
int dp[N*N];
signed main()
{
cin>>n>>c;
for(int i=1; i<=n; i++)
{
cin>>v[i]>>w[i];
sum+=v[i];
}
memset(dp,0x3f,sizeof dp);
dp[0]=0;
for(int i=1; i<=n; i++)
{
for(int j=sum; j>=v[i]; j--)
{
dp[j]=min(dp[j],dp[j-v[i]]+w[i]);
}
}
for(int i=sum; i>=0; i--)
{
if(dp[i]!=0x3f3f3f3f&&dp[i]<=c)
{
cout<<i<<"\n";
return 0;
}
}
return 0;
}
数据可能有点水,0x3f还是有点小感觉
3.价值和体积都很大,搜索
小奇采药
题目描述
小奇是只天资聪颖的喵,他的梦想是成为世界上最伟⼤的医师。
为此,他想拜喵星球最有威望的医师为师。
医师为了判断他的资质,给他出了⼀个难题。
医师把他带到⼀个到处都是草药的⼭洞里对他说:“小奇,这个⼭洞里有⼀些不同的草药,采每⼀株都需要⼀些时间,每⼀株也有它自身的价值。
我会给你⼀段时间,在这段时间里,你可以采到⼀些草药。
如果你是⼀只聪明的喵,你应该可以让采到的草药的总价值最⼤。”
输入
第R⾏包括R个整数h,表示数据组数。
对于每组数据,第R⾏包括k个整数,M,K,表示草药的数目和能用于采药的时间。
接下来M⾏,每⾏两个整数ti,vi。
保证m,ti,vi在限制范围内均匀随机⽣成。
输出
输出h⾏,每⾏R个数字,表示每组数据答案。
样例输入
1 3 70 71 100 69 1 1 2
样例输出
3
提示
对于30%数据,1≤n≤20,1≤m,vi,ti≤10^4
对于60%数据,1≤n≤100,1≤m,vi,ti≤10^5
对于100%数据,1≤T≤10,1≤n≤150,1≤m,vi,ti≤10^9
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll st[155],sv[155];
ll t,n,m,ans;
struct node
{
ll times,value;
}s[155];
bool cmp(node a,node b)
{
return a.times>b.times;
}
void dfs(ll x,ll sumt,ll sumv)
{
ans=max(ans,sumv);
if(sumt+s[n].times>m)return;
if(sumv+sv[x]<ans)return ;
if(sumt+st[x]<=m)
{
ans=max(ans,sumv+sv[x]);
return ;
}
if(sumt+s[x].times<=m)dfs(x+1,sumt+s[x].times,sumv+s[x].value);
dfs(x+1,sumt,sumv);
}
int main()
{
scanf("%lld",&t);
while(t--)
{
scanf("%lld%lld",&n,&m);
for(int i=1;i<=n;i++)scanf("%lld%lld",&s[i].times,&s[i].value);
sort(s+1,s+1+n,cmp);
for(int i=n;i>=1;i--)
{
st[i]=st[i+1]+s[i].times;
sv[i]=sv[i+1]+s[i].value;
}
ans=0;
dfs(1,0,0);
printf("%lld\n",ans);
}
return 0;
}
4.双向搜索
送礼物
达达帮翰翰给女生送礼物,翰翰一共准备了 N 个礼物,其中第 i 个礼物的重量是G[i]。
达达的力气很大,他一次可以搬动重量之和不超过 W 的任意多个物品。
达达希望一次搬掉尽量重的一些物品,请你告诉达达在他的力气范围内一次性能搬动的最大重量是多少。
输入格式
第一行两个整数,分别代表 W 和 N。
以后 NN 行,每行一个正整数表示 G[i]。
输出格式
仅一个整数,表示达达在他的力气范围内一次性能搬动的最大重量。
数据范围
1≤N≤46
1≤W,G[i]≤2^31−1
输入样例:
20 5
7
5
4
18
1
输出样例:
19
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 1 << 24;
int n, m, k;
int g[50], weights[N];
int cnt = 0;
int ans;
void dfs(int u, int s)
{
if (u == k)
{
weights[cnt ++ ] = s;
return;
}
if ((LL)s + g[u] <= m) dfs(u + 1, s + g[u]);
dfs(u + 1, s);
}
void dfs2(int u, int s)
{
if (u == n)
{
int l = 0, r = cnt - 1;
while (l < r)
{
int mid = l + r + 1 >> 1;
if (weights[mid] + (LL)s <= m) l = mid;
else r = mid - 1;
}
if (weights[l] + (LL)s <= m) ans = max(ans, weights[l] + s);
return;
}
if ((LL)s + g[u] <= m) dfs2(u + 1, s + g[u]);
dfs2(u + 1, s);
}
int main()
{
cin >> m >> n;
for (int i = 0; i < n; i ++ ) cin >> g[i];
sort(g, g + n);
reverse(g, g + n);
k = n / 2;
dfs(0, 0);
sort(weights, weights + cnt);
int t = 1;
for (int i = 1; i < cnt; i ++ )
if (weights[i] != weights[i - 1])
weights[t ++ ] = weights[i];
cnt = t;
dfs2(k, 0);
cout << ans << endl;
return 0;
}
总结到此为止,仅用于记录