题目描述
有 n 个学生站成一排,每个学生有一个能力值,牛牛想从这 n 个学生中按照顺序选取 k 名学生,要求相邻两个学生的位置编号的差不超过 d,使得这 k 个学生的能力值的乘积最大,你能返回最大的乘积吗?
输入描述:
每个输入包含 1 个测试用例。每个测试数据的第一行包含一个整数 n (1 <= n <= 50),表示学生的个数,接下来的一行,包含 n 个整数,按顺序表示每个学生的能力值 ai(-50 <= ai <= 50)。接下来的一行包含两个整数,k 和 d (1 <= k <= 10, 1 <= d <= 50)。
输出描述:
输出一行表示最大的乘积。
示例1
输入
3 7 4 7 2 50
输出
49
采用动态规划。设Maxval[i][j]表示以第i个人为最后一个人,一共选取了j+1个人时的最大乘积。
同理,Minval[i][j]表示同样状态下的最小乘积(由于数据中存在负数,负数乘上某个极大的负数反而会变成正的极大值,因而需要同时记录最小值)。
Maxval[i][j]很显然与Maxval[i][j-1]相关,可以理解为Maxval[i][j]由两部分组成,一部分是自身作为待选值,
另一部分是Maxval[i][j-1]乘上一个人后得到的值,然后取它们的极大值,由此可以得到状态转移方程如下:
//mn[i][j]表示前i个人选了j个人并且以第i个人为结尾满足相邻位置差不大于d的最小值
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;
const int N = 110;
const long long inf = 1e16;
long long a[N], mx[N][15], mn[N][15];
//事先声明了数组,因为最后数可能会很大,所以定义的longlong类型
int main()
{
int n;
while(scanf("%d", &n) > 0)
{
for(int i = 1; i <= n; i++)
//这种输入数组的方法
{
scanf("%lld", &a[i]);
}
int d, m;
scanf("%d%d", &m, &d);
for(int i = 1; i <= n; i++)
{
mx[i][0] = 1;
mn[i][0] = 1;
for(int j = 1; j <= m; j++)
{
mx[i][j] = -inf;
mn[i][j] = inf;
}
}
long long mmx = -100, mmn = 100;
//mmx主要是用于当k=1时选出数组中最大的元素
long long ans = -inf;
for(int i = 1; i <= n; i++)
{
mmx = max(mmx, a[i]);
mx[i][1] = a[i];
mn[i][1] = a[i];
if(m == 1)
ans = max(ans, mmx);
}
for(int i = 1; i <= n; i++)
{
for(int j = 2; j <= m && j <= i; j++)
{
for(int k = i - 1; k >= max(1, i - d) && k >= j - 1; k--)
//mx[r][j-1]表示从前r个中选出j-1个最大的乘积,所以r>=j-1;r只能最多回溯d个或者回溯到底
{
mx[i][j] = max(mx[i][j], mx[k][j - 1] * a[i]);
mx[i][j] = max(mx[i][j], mn[k][j - 1] * a[i]);
mn[i][j] = min(mn[i][j], mn[k][j - 1] * a[i]);
mn[i][j] = min(mn[i][j], mx[k][j - 1] * a[i]);
if(j == m)ans = max(ans, mx[i][j]);
}
}
}
printf("%lld\n", ans);
}
}
题目描述
牛牛想尝试一些新的料理,每个料理需要一些不同的材料,问完成所有的料理需要准备多少种不同的材料。
输入描述:
每个输入包含 1 个测试用例。每个测试用例的第 i 行,表示完成第 i 件料理需要哪些材料,各个材料用空格隔开,输入只包含大写英文字母和空格,输入文件不超过 50 行,每一行不超过 50 个字符。
输出描述:
输出一行一个数字表示完成所有料理需要多少种不同的材料。
示例1
输入
BUTTER FLOUR HONEY FLOUR EGG
输出
4
#include<string>
#include<set>
#include<iostream>
using namespace std;
int main()
{
set<string> st;
string str_tmp;
while(cin>>str_tmp)
st.insert(str_tmp);
cout << st.size();
return 0;
}
cin的输入忽略空格和回车。scanf("%c",&i)等价于i = getchar(),换行符和回车都会被读入。
题目描述
n 只奶牛坐在一排,每个奶牛拥有 a
i 个苹果,现在你要在它们之间转移苹果,使得最后所有奶牛拥有的苹果数都相同,每一次,你只能从一只奶牛身上拿走恰好两个苹果到另一个奶牛上,问最少需要移动多少次可以平分苹果,如果方案不存在输出 -1。
输入描述:
每个输入包含一个测试用例。每个测试用例的第一行包含一个整数 n(1 <= n <= 100),接下来的一行包含 n 个整数 ai(1 <= ai <= 100)。
输出描述:
输出一行表示最少需要移动多少次可以平分苹果,如果方案不存在则输出 -1。
示例1
输入
4 7 15 9 5
输出
3
#include<iostream>
#include<algorithm>
using namespace std;
int a[100];
int main()
{
int n;
while(scanf("%d",&n)>0)
{
int sum=0;
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
sum=sum+a[i];
}
int flag=0;
if(sum%n!=0)//如果总数不能被平分,那么怎么挪也是失败
flag=1;
int avg=sum/n,cnt=0;
for(int i=1;i<=n;i++)
{
if(abs(a[i]-avg)%2!=0)//如果有的不能通过每次挪两个达到平均值那么就会失败
flag=1;
cnt+=abs(a[i]-avg)/2;
}
if(flag)
cout<<-1<<endl;
else
cout<<cnt/2<<endl;//每次挪动解决两个奶牛的问题,所以要除2
}
}
题目描述
航天飞行器是一项复杂而又精密的仪器,飞行器的损耗主要集中在发射和降落的过程,科学家根据实验数据估计,如果在发射过程中,产生了 x 程度的损耗,那么在降落的过程中就会产生 x
2 程度的损耗,如果飞船的总损耗超过了它的耐久度,飞行器就会爆炸坠毁。问一艘耐久度为 h 的飞行器,假设在飞行过程中不产生损耗,那么为了保证其可以安全的到达目的地,只考虑整数解,至多发射过程中可以承受多少程度的损耗?
输入描述:
每个输入包含一个测试用例。每个测试用例包含一行一个整数 h (1 <= h <= 10^18)。
输出描述:
输出一行一个整数表示结果。
示例1
输入
10
输出
2
#include<cmath>
#include<iostream>
using namespace std;
int main()
{
long long data;
while(scanf("%lld",&data) > 0)
{
cout << int((sqrt(4 * data + 1) - 1) / 2.0)<< endl;
}
return 0;
}
题目描述
牛牛拿到了一个藏宝图,顺着藏宝图的指示,牛牛发现了一个藏宝盒,藏宝盒上有一个机关,机关每次会显示两个字符串 s 和 t,根据古老的传说,牛牛需要每次都回答 t 是否是 s 的子序列。注意,子序列不要求在原字符串中是连续的,例如串 abc,它的子序列就有 {空串, a, b, c, ab, ac, bc, abc} 8 种。
输入描述:
每个输入包含一个测试用例。每个测试用例包含两行长度不超过 10 的不包含空格的可见 ASCII 字符串。
输出描述:
输出一行 “Yes” 或者 “No” 表示结果。
示例1
输入
x.nowcoder.com ooo
输出
Yes
#include<iostream>
#include<cstring>
using namespace std;
int main()
{
string str1;
while(cin >> str1)
{
string str2;
cin >> str2;
int a = 0;
int b = 0;
while (a < str1.length())
{
if (str1[a++] == str2[b])
b++;
}
if (b == str2.length())
cout << "Yes" << endl;
else
cout << "No" << endl;
}
return 0;
}
题目描述
牛牛的作业薄上有一个长度为 n 的排列 A,这个排列包含了从1到n的n个数,但是因为一些原因,其中有一些位置(不超过 10 个)看不清了,但是牛牛记得这个数列顺序对的数量是 k,顺序对是指满足 i < j 且 A[i] < A[j] 的对数,请帮助牛牛计算出,符合这个要求的合法排列的数目。
输入描述:
每个输入包含一个测试用例。每个测试用例的第一行包含两个整数 n 和 k(1 <= n <= 100, 0 <= k <= 1000000000),接下来的 1 行,包含 n 个数字表示排列 A,其中等于0的项表示看不清的位置(不超过 10 个)。
输出描述:
输出一行表示合法的排列数目。
示例1
输入
5 5 4 0 0 2 0
输出
2
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
int cal(vector<int> tmp)
{
int ans = 0;
int len = tmp.size();
for (int i = 0; i < len; i++)
{
for (int j = i + 1; j < len; j++)
{
if (tmp[i] < tmp[j])
ans++;
}
}
return ans;
}
int main()
{
int n,k;
while(cin>>n>>k)
{
int ans = 0;
vector<int> A(n);
vector<int> c1;
vector<int> c2;
vector<int> index;
for (int i = 0; i < n; i++)
{
cin >> A[i];
if (A[i] != 0)
c1.push_back(A[i]);
else
index.push_back(i);
}
for (int i = 1; i <= n; i++)
{
if (find (c1.begin(), c1.end(), i) == c1.end())
c2.push_back(i);
}
do
{
vector<int> tmp = A;
int c2len = c2.size();
for (int i = 0; i < c2len; i++)
{
tmp[index[i]] = c2[i];
}
if(cal(tmp) == k)
ans++;
}while(next_permutation(c2.begin(),c2.end()));
cout << ans << endl;
}
}