A、B、C、D四道题题解
一.A题
(1)题意:
有t组测试数据,每组测试数据有n个数,且这n个数按升序输入,问这组数据里面能不能选出三个数,使他们不能凑成三角形,能就输出三个数的位置,不能就输出-1。
(2)题解:
三角形的特性是两边之和大于第三边,两边之差小于第三边。
所以我们直接判断最大的差与剩下最小的数的关系,即a[n] - a[1]与a[2]的关系,假如a[n] - a[1] < a[2]的话,说明这n个数的差距不大,并不能出现两边之差大于等于第三边,两边之和小于等于第三边的情况。
其他情况下就直接输出1,2,n即可。
(3)代码:
#include <stdio.h>
#include <string>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <cstring>
#include <iostream>
#include <algorithm>
#include<functional>
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 10;
const int INF = 0x3f3f3f3f;
int a[maxn],t,n;
bool check()
{
if(a[n] - a[1] < a[2])
return true;
return false;
}
int main()
{
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
for(int i = 1; i <= n; i++)
scanf("%d",&a[i]);
//sort(a+1,a+1+n);
if(check())
{
printf("-1\n");
}
else{
printf("%d %d %d\n",1,2,n);
}
}
return 0;
}
二.B题
(1)题意:
给t组数据,每组数据有一个字符串s,字符串由‘0’和‘1’组成。Alice和Bob玩游戏,Alice先走,每次可以选择不少于1的任意长度的连续相等字符,然后消除掉:
例如 110011,可以选择[1,2] -> 0011,也可以选择[3,4] -> 1111
每次选择了一个1,就加一分,问都选择最优策略的情况下,Alice最多可以获得多少分?
(2)题解:
因为是交错选择,所以选择连续的‘0’是不理智的行为,这样的话就会让Bob一次选择到更多的‘1’,同样的Bob也不会做这样的行为,所以就是每次选择当前最多连续‘1’。
统计出所有连续的‘1’,然后排个序,在交叉选择,就是Alice的最多可获取的分数。
(3)代码:
#include <stdio.h>
#include <string>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <cstring>
#include <iostream>
#include <algorithm>
#include<functional>
using namespace std;
typedef long long ll;
const int maxn = 1e4 + 10;
const int INF = 0x3f3f3f3f;
int t,a[maxn];
bool cmp(int x,int y)
{
return x > y;
}
int main()
{
scanf("%d",&t);
while(t--)
{
memset(a,0,sizeof(a));
int flag = 0,cnt = 0,ans = 0;
string str;
cin>>str;
for(int i = 0; i < str.size(); i++)
{
if(str[i] == '1' && flag == 0)
{
cnt++;
flag++;
}
else if(str[i] == '1' && flag != 0)
{
flag++;
}
else if(str[i] == '0' && flag != 0)
{
a[cnt] += flag;
flag = 0;
}
}
if(flag != 0)
a[cnt] = flag;
sort(a+1,a+1+cnt,cmp);
for(int i = 1; i <= cnt; i++)
{
if(i % 2 == 1)
ans += a[i];
}
printf("%d\n",ans);
}
return 0;
}
三.C题
(1)题意:
有t组测试数据,每组数据有n个数,这些数连续输入且每个数的大小在‘0’~‘9’之内,问有多少个子串满足a[l] + a[l+1] ……+a[r] = r- l + 1?
(2)题解:
首先要知道每当连续遇到一个满足条件的值的时候,ans是当前数的累加,例如1111 -> ans = 1+2+3+4;
其次每当遇见一个大于1的数 a[i] 就得向前或者向后寻找到a[i] - 1个0才能又满足条件;同理遇到一个0也是一样的;
所以我们把所有值-1,这样1 -> 0就不会影响我们维护的前缀值,然后 0 -> -1就代表需要向前或者向后找到1来填补,在这个过程中我们来维护前缀值。
(3)代码:
#include <stdio.h>
#include <string>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <cstring>
#include <iostream>
#include <algorithm>
#include<functional>
using namespace std;
typedef long long ll;
const int maxn = 1e2 + 10;
int t,n;
int main()
{
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
ll k = 0, ans = 0;
map<int,int> sum;
sum[0] = 1;
for(int i = 0; i < n; i++)
{
char ch;
scanf(" %c",&ch);
k += ch - '0' - 1;
ans += sum[k];
sum[k]++;
//这里sum[k]++是因为有类似于500005这样的情况,向前向后填坑都是满足条件
//所以ans不单单只加上 sum = 0的时候
}
printf("%lld\n",ans);
}
return 0;
}
四.D题
(1)题意:
有三种颜色的木棍分别有各R、G、B对,每次选择两对不同颜色的木棍组成一个矩形,问所有能组成的矩形面积之和是多少
(2)题解:
因为R、G、B都不超过200,所有三重for循环的dp是满足的,下面确定各个变量与状态转移方程:
r[i] : 第一种颜色的第 i 对木棍长度
g[i] : 第二种颜色的第 i 对木棍长度
b[i] : 第三种颜色的第 i 对木棍长度
dp[i][j][k]:前 i 对 r ,前 j 对 g ,前 k 对 b的最大值
每次当 i >= 1 && j >= 1 说明 i ,j 可取,dp[i][j][k] = max(dp[i][j][k] , dp[i-1][j-1][k] + r[i] * g[j]);
同理剩下 i >= 1 && k >= 1 和 j >= 1 && k >= 1也是一样的。
(3)代码:
#include <stdio.h>
#include <string>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <cstring>
#include <iostream>
#include <algorithm>
#include<functional>
using namespace std;
typedef long long ll;
const int maxn = 2e2 + 10;
ll r[maxn], g[maxn], b[maxn];
ll dp[maxn][maxn][maxn];
int R,G,B;
int main()
{
scanf("%d%d%d",&R,&G,&B);
for(int i = 1; i <= R; i++)
scanf("%lld",&r[i]);
for(int i = 1; i <= G; i++)
scanf("%lld",&g[i]);
for(int i = 1; i <= B; i++)
scanf("%lld",&b[i]);
sort(r+1, r+1+R);
sort(g+1, g+1+G);
sort(b+1, b+1+B);
for(int i = 0; i <= R; ++i){
for(int j = 0; j <= G; ++j){
for(int k = 0; k <= B; ++k){
if(i&&j)
dp[i][j][k] = max(dp[i][j][k], dp[i-1][j-1][k] + r[i]*g[j]);
if(j&&k)
dp[i][j][k] = max(dp[i][j][k], dp[i][j-1][k-1] + g[j]*b[k]);
if(i&&k)
dp[i][j][k] = max(dp[i][j][k], dp[i-1][j][k-1] + r[i]*b[k]);
}
}
}
printf("%lld\n",dp[R][G][B]);
return 0;
}