A小红购物;链接:A-小红购物_牛客周赛 Round 25 (nowcoder.com)
题意:
给出了n件物品,每件物品的价格是ai,每件物品可以退货或者是购买,退货的话要消耗路费max(5,a[i]/100)
给出n,以及n个物品的价格,以及一个字符串,T代表购买,F表示退货
思路:简单模拟,按照题意进行操作
代码:
#include <iostream>
#include <vector>
#include <cstring>
using namespace std;
typedef long long ll;
int main()
{
ll n,sum=0;
cin>>n;
vector<ll>v(n);
for(int i=0;i<=n-1;i++)
cin>>v[i];
string s;
cin>>s;
for(int i=0;i<s.size();i++)
{
if(s[i]=='T')
{
sum+=v[i];
}else
{
ll k=v[i]/100;
ll t=5;
sum+=max(t,k);
}
}
cout<<sum;
return 0;
}
B小红吃桃链接:B-小红吃桃_牛客周赛 Round 25 (nowcoder.com)
题意:给出两个长度一样的数组,求令两个数组各自相乘,最后两个数组相乘积的和最大,对1e9+7求余数
思路:其实按照例子就可以了,让两个数组中第i个位置的数较大的一个放到第一个数组中,另一个较小的放到第二个数组
代码:
#include <iostream>
#include <vector>
#include <cstring>
using namespace std;
typedef long long ll;
const ll N=1e9+7;
int main()
{
ll n,sum1=1,sum2=1,sum=0;
cin>>n;
vector<ll>v1(n+1);
vector<ll>v2(n+1);
for(int i=1;i<=n;i++)
cin>>v1[i];
for(int i=1;i<=n;i++)
cin>>v2[i];
for(int i=1;i<=n;i++)
{
if(v1[i]>=v2[i])
{
swap(v1[i],v2[i]);
}
sum1*=v1[i];
sum1%=N;
sum2*=v2[i];
sum2%=N;
}
sum+=sum1+sum2;
sum%=N;
cout<<sum;
return 0;
}
C小红的踏浪斩C-小红的踏前斩_牛客周赛 Round 25 (nowcoder.com)
题意:有n个怪物排成一列,第i个怪物的血量是ai,有两种操作
第一种,消耗1点mp,造成1点伤害
第二种,消耗5点mp,对第一个怪物造成1点伤害,第二个2点,第三个3点
当怪物血量小于等于0的的时候,怪物死亡,但怪物还在原地,还会被2伤害
思路:假如从前开始使用技能2,那么我能可以思考到前面的部分会对后面的技能2的使用造成影响
比如:
对第一个怪和第二个怪分别进行一次强力攻击,此时每只怪物血量为[1,2,4,2,3]
对第一个怪进行一次踏前斩,此时每只怪物血量为[0,0,1,2,3]
再对第三个怪进行一次踏前斩,消灭全部怪物。
总mp消耗为12。
从例子中能看出前面的会对后面的造成影响
所以我们可以从后面开始进行操作2,根据题意我们能知道我们一定要最大化的使用操作2
代码:
#include <iostream>
#include <bits/stdc++.h>
#include <algorithm>
using namespace std;
const int INF = 1e9+7;
typedef long long ll;
int main() {
ll n,sum=0;
cin >> n;
vector<int> a(n+1);
for (int i = 1; i <= n; i++) {
cin >> a[i];
}
vector<int> dp(n + 1, INF);
for (int i = n-2; i >=1; i--) {
if(a[i]>=1&&a[i+1]>=2&&a[i+2]>=3) {
ll k = min({a[i] , a[i + 1] / 2, a[i+2]/3});
sum += k * 5;
a[i] -= k;
a[i + 1] -= k * 2;
a[i + 2] -= k*3;
}
// sum+=a[i]+a[i-1]+a[i-2];
}
for (int i = n; i >=1; i--) {
if(a[i]!=0)
sum+=a[i];
// sum+=a[i]+a[i-1]+a[i-2];
}
// int cost = dp[n];
cout << sum << endl;
return 0;
}
D题期末结束补充//期末结束,开始补充
D小红树
题意:给一个字符串,每个结点有着对应颜色,每条边的权值,消除一个边,两边同色连通块数量之差的绝对值,就是这个边的权值,求所有边权和
思路:刚学完树形dp,特别像,它通过从结点1出发,然后不断向下直到叶子结点再将叶子结点处的块数标记加1,然后再进行不断回溯,对父节点进行更新增加,假如说子节点和父节点的颜色一样,那么父节点的块数统计减减,因为会多一个块被计算进去
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 2e5 + 10;
int n; //n为节点总数
int f[N]; //f[]储存连通块数量。以f[i]为根,向下加上自身的连通块数
string s; //存储颜色
vector<int>g[N];//用于储存树
ll res; //统计总数
//通过深搜遍历树,统计以u为根的连通块的数目
void dfs_1(int u, int father)
{
f[u] = 1;//赋值 根u 连通块初始值为 1(自身)
for (int x:g[u])//遍历g[u]为根向下的节点
{
if (x == father) continue;//当遍历到指向的根方向时,跳过
dfs_1(x, u);
f[u] += f[x]; //统计连通块数量
if (s[u] == s[x]) f[u] --;//题目要求统计同色连通块
//当遍历到同色连通块时 f[u] - 1
}
}
//计算两个子树同色连通块的差值,并统计存入res中
void dfs_2(int u, int father)
{
for (int x:g[u])//遍历g[u]为根向下的节点
{
if (x == father) continue;//当遍历到指向的根方向时,跳过
dfs_2(x, u);
//f[x]为以x为根的子树的连通块数量
//v 为另一个子树的连通块的数量
int v = f[1] - f[x];
if (s[u] == s[x]) v ++;//若原本为同色,在分开始必然增加同色连通块的数量
res += abs(v - f[x]);//统计,存入res中
}
}
int main()
{
int a, b;
ios::sync_with_stdio(false);
cin >> n >> s;
s = '$' + s;//使颜色与f[]的下标相统一
n --;
while(n --)
{
//输入结点,建立连接结点的线
cin >> a >> b;
g[a].push_back(b);
g[b].push_back(a);
}
dfs_1(1, -1);
dfs_2(1, -1);
cout << res << endl;
return 0;
}
浙公网安备 33010602011771号