蓝桥 倒水(变形的01背包)
首先用一点贪心算法的思想 , 我们知道,在倒水量(0,a)之间获得e的满意度,倒水量(a,c)的区间获得b的满意度,大于等于c获得d的满意度(以上括号都是左闭右开)。那么想要让倒水值尽可能小,我们就可以只选择0,a,c三个倒水量。
通过以上分析,我们有0对应e的满意度 , a对应b的满意度 , c对应d的满意度,这里注意,不同于普通背包的是,在普通的01背包中, 我们可以选择一下物品不取,而在这里所有物品都需要取,也就是我们需要给所有人倒水,所以遍历方式可能就不一样。
首先我们还是正常定义数组
cin>>n>>m;
for(int i =1;i<=n;++i)cin>>a[i]>>b[i]>>c[i]>>d[i];
还是像01背包一样,先遍历物品再遍历背包,但是此时要注意遍历背包时与正常的01背包不同
for(int i=1;i<=n;++i)
for(int j =m;J>=0;--j)
此时是大于等于0了,这就是不同点
那么对于j(也就是倒水量)来说就有三种可能
if(j < a[i])
else if(j >= a[i] && j < c[i])
else
在这三种可能中,我们来分类说一下
1、第一种情况,j < [I],那么此时就不能倒水了
dp[j] = dp[j] + e[i];
2、第二种情况 , 我们可以选择倒a[i]水或者不倒水
dp[j] = max(dp[j] + e[i] , dp[j - a[i]]+b[i]);
3、第三种情况,我们可以选择不倒水 , 倒a[i],倒c[i]
dp[j] =max(dp[j]+e[i] , max(dp[j - a[i]]+b[i] , dp[j- c[i]] + d[i]);
那么分析到这里,这道题目也就做完了。
下面请看ac代码
#include <bits/stdc++.h>
using namespace std;
const int N =1e4;
long long dp[N];
int a[N] , b[N] ,c[N],d[N],e[N];
int n,m;
int main(){
cin>>n>>m;
for(int i =1;i<=n;++i)cin>>a[i]>>b[i]>>c[i]>>d[i]>>e[i];
for(int i = 1;i<=n;++i){
for(int j = m;j>=0;--j){
if(j < a[i])dp[j] = dp[j] +e[i];
else if(j >=a[i] && j <c[i]){
dp[j] = max(dp[j]+e[i] , dp[j - a[i]] + b[i]);
}
else{
dp[j] = max(dp[j]+e[i] , max(dp[j - c[i]] + d[i] , dp[j-a[i]]+b[i]));
}
}
}
cout<<dp[m];
return 0;
}
洛谷 5倍经验日(变形01背包)(与上一题几乎一样,类题)
传送门:洛谷 5倍经验日
话不多说,这题与上题基本一样,前面的输入数组啊之类的就不说了,说一下重点
首先这题依然是所有人都要打也就是所有物品都要取,那么就是
for(int i =1;i<=n;++i)
for(int j =m;j>=0;--j)
但不同的是这题只有两种可能了,不像上一题有三种/
1、精力够打这个人 也就是
if(j >= c[i])
dp[j] = max(dp[j] ,dp[j - c[i]]+b[i])
2、精力不够了
if(j < c[i]){
dp[j] = dp[j] + a[i];
}
那么就做完了
下面是ac代码
#include <bits/stdc++.h>
using namespace std;
using ll =long long;
const int N = 1e3 + 9;
ll a[N] ,b[N] , c[N] , dp[N];
int n,m;
int main(){
cin>>n>>m;
for(int i =1;i<=n;++i)cin>>a[i]>>b[i]>>c[i];
for(int i =1;i<=n;++i){
for(int j =m;j>= 0;--j){
if(j >= c[i])dp[j] = max(dp[j]+a[i],dp[j-c[i]]+b[i] );
else dp[j] = dp[j]+a[i];
}
}
cout<<dp[m] * 5;
return 0;
}
洛谷 笨小猴(哈希表 , 优先队列)
传送门:笨小猴
这题用普通的哈希数组就能做,但是我用的是比较高大上(哈哈)的解法,那就是map+优先队列
我们用map对每个数字进行存储
string s;cin>>s;
for(auto num : s) mp[num]++;
那么如何从大到小排序呢,我使用了优先队列,注意的是此时用pair加入对优先队列
priority_queue<pair<int , int >>q;
for(auto [x ,y]:mp){
q.emplace(y,x);
}
下一步就是如何找出现频率最高的数和最低的数,那么最高频率的数已经被我们的优先队列储存起来了,而且就在第一个,最低频率的数在最后一个
int ma = q.top().first;
while(q.size() !=1){
q.pop();
}
int mi = q.top().sfirst;
剩下就很容易计算出差值,并且写一个布尔函数判断是否为质数(要注意1,0都不是质数,我就因为这个一开始只拿了50分,后来加上去就ac了),那么本题就做完了
下面是ac代码
#include <bits/stdc++.h>
using namespace std;
map<int,int>m;
priority_queue<pair<int,int>>q;
bool check(int x){
if(x == 0 ||x ==1)return false;
for(int i =2;i<x;++i){
if((x%i) == 0)return false;
}
return true;
}
int main(){
string s;
cin>>s;
for(auto num : s){
m[num]++;
}
for(auto [x,y]:m){
q.emplace(y,x);
}
int ma = q.top().first;
int mi = 0;
while(q.size() != 1){
q.pop();
}
mi = q.top().first;
int c = ma - mi;
if(check(c)){
cout<<"Lucky Word"<<'\n';
cout<<c;
}
else {
cout<<"No Answer"<<'\n';
cout<<0;
}
}
洛谷 连续自然数和(数学)
传送门:P1147 连续自然数和 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
首先因为是连续的自然数和,我们可以想到等差数列首项加尾项乘项数除二,假设尾项是r,首项是l的话就是 (l+r)(r-l+1)/2 = m(m是题里面给的那个和),转换一下就是 (l + r)(r-l+1) = 2m
所以(l+r)和(r-l+1)是2m的两个因子,那么我们可以先找找2m都有哪些因子,用一个vector数组存储起来
vector<int >x;
for(int i=2;i<2*m;++i){
if(2*m % i == 0){
x.push_back(i);
}
}
此时2m的所有因子就进入了这个数组了。
接下来是本题另一个关键所在:
我们设2m的两个因子为 x 和 y,那么
l + r =x
r-l +1 =y
我们可以解出r = (x -y +1)/2; l =x -r;
说明两个因子相减+1是可以被二整除的,那我们可以枚举两个因子
for(auto num1 : x)
for(auto num2 : x)
if((num1 - num2 +1)%2)continue; //不能被整除,跳过
int r = (num1 -num2 +1)/2;
int l =num1 -l;
最后我们还要看l和r是否合法,合法的话用数组存起来
vector<pair<int,int>>ans;
if(0 <=l && l<=r &&(l+r)*(r-l+1)==2*m)
ans.push_back({l,r});
最后是ac代码
#include <bits/stdc++.h>
using namespace std;
int n;
int main(){
cin>>n;
vector<int>x;
for(int i =2;i<2 * n;++i){
if((2 * n) % i == 0)x.push_back(i); // i是因子
}
vector<pair<int,int>>ans;
for(auto num1 : x){
for(auto num2 : x){
if((num1 - num2 + 1)%2)continue;
int l = (num1 - num2 +1) / 2;
int r = num1 - l;
//判断合法性
if(0<= l && l <=r &&(r- l +1)*(r + l) == 2* n){
ans.push_back({l,r});
}
}
}
sort(ans.begin() , ans.end());
for(auto [x ,y] : ans){
cout<<x<<' '<<y<<'\n';
}
return 0;
}
结束了,完结撒花,如果喜欢这篇文章可以点赞支持哦!!!