比赛链接
A题 解题思路:
#include
#include
#include
#include
#include
#include
using namespace std;
char a[10][10];
int ans[100];
int main(){
int t;
scanf("%d",&t);
for (int j = 1; j <= t; j++){
int n = 10;
int x = 0, y = 0;
for (int i = 0 ; i < n; i++){
scanf("%d",&ans[i]);
if (ans[i] == 17){
x = 1;
}
if (ans[i] == 18){
y = 1;
}
}
for (int i = 0; i <n; i++){
if (i == n - 1){
printf("%d",ans[i]);
}
else printf("%d ",ans[i]);
}
printf("\n");
if (x && y){
printf("both\n");
}
else if (!x && !y){
printf("none\n");
}
else if (x == 1){
printf("zack\n");
}
else{
printf("mack\n");
}
printf("\n");
}
return 0;
}
和A题类似
#include
#include
#include
#include
#include
#include
using namespace std;
char a[10][10];
int ans[100];
int main(){
int t;
scanf("%d",&t);
for (int j = 1; j <= t; j++){
int a, b, c, d, e, f;
scanf("%d%d%d%d%d%d",&a, &b,&c, &d, &e, &f);
int res = a + b + c;
int num = f +d + e;
int x = 0, y = 0;
if (res > num){
x = 1;
}
if (a > d || (a >= d && b > e) || (a == d && b == e && c > f)){
y = 1;
}
printf("%d %d %d %d %d %d\n",a,b,c,d,e,f);
if (x && y){
printf("both\n");
}
else if (!x && !y){
printf("none\n");
}
else if (x){
printf("count\n");
}
else{
printf("color\n");
}
printf("\n");
}
return 0;
}
C题也是道水题,只要当前的蛋糕数小于等于来的人数,那么就 * 2,然后排着输出即可。
#include
#include
#include
#include
using namespace std;
int main(){
int t;
scanf("%d",&t);
int q = 1;
while(t--){
int n, m;
scanf("%d%d",&n,&m);
int k;
printf("Practice #%d: %d %d\n",q,n,m);
scanf("%d",&k);
for (int i = 0; i < k; i++){
int p;
scanf("%d",&p);
while (p >= m){
m *= 2;
}
m -= p;
printf("%d %d\n",p,m);
}
q++;
printf("\n");
}
return 0;
}
D题我感觉是ABCDEFG里最难的(可能是当时脑子糊涂了)
首先肯定是每次更新最小值,我们使用最小值去购买,然后主要是计算糖比较麻烦(想哭)
首先我们用我们需要的糖与我们剩下的糖做比较,如果剩下的 >= 需要的那么就不必购买,随后我们用剩下的 -= 需要的即可,如果是 > , 那么我们需要的减去剩下的,然后再进行计算。
#include
#include
#include
using namespace std;
int main(){
int t;
scanf("%d",&t);
for (long long i = 1; i <= t; i++){
long long d, n, s;
scanf("%lld%lld%lld",&d,&n,&s);
long long mn = 1e9;
long long ms = 1e9;
long long b, c;
long long res = 0;
long long m = 0;
int a ;
for (long long j = 1; j <= d; j ++){
scanf("%d%lld%lld",&a,&b,&c);
if (b < mn){
mn = b;
}
if (c < ms){
ms = c;
}
res += n * a *mn;
if (m >= a * n *ms){
m -= a * n * ms;
continue;
}
else{
long long result = a * s - m;
m = 0;
if (result % 80 == 0){
res += result / 80 * ms;
}
else{
m += (80 - (result % 80));
res += ms * (result/80 + 1);
}
}
}
cout<<res<<endl;
}
return 0;
}
稍微有点麻烦,首先我们进行分类:
#include
#include
#include
#include
#include
using namespace std;
const double P = 3.14159265358979;
int main(){
int t;
scanf("%d",&t);
while(t--){
double d, r;
double res ;
scanf("%lf%lf",&d,&r);
double d1 = d * 1.0/sqrt(2);
if (d1 <= r){
res = d * d;
printf("%.2f\n",res);
}
else if (d >= 2 * r){
res = P * r * r;
if (res * 100 - (int)(res * 100) >= 0.5) res += 0.005;
printf("%.2f\n",res);
}
else{
double k = (sqrt(r * r - (d * 1.0 / 2) * (d * 1.0/2)) * d * 1.0 / 2) * 4; // 三角形面积
double a = sqrt(r * r - (d * 1.0 / 2) * (d * 1.0/2)) / r; // 求出sin 的比值
double b = asin(a); // 求出相应的弧度
b = b * 360/(2*P); // 求出相对应的角度
b = 90 - 2 * b; // 求出扇形对应的角度
double l = b * P * r * r /360 ; // 求出扇形的面积
res = l * 4 + k;
if (res * 100 - (int)(res * 100) >= 0.5) res += 0.005;
printf("%.2f\n",res);
}
}
return 0;
}
给予字符串,其中 a, e, i, o, y 是原因,其他的为辅音,要求元音辅音交叉存在(偶数),其实就是两种情况:
#include
#include
#include
#include
#include
#include
using namespace std;
set <char> ss;
vector<int> mul(vector<int> &A, int b)
{
vector<int> C;
int t = 0;
for (int i = 0; i < A.size() || t; i ++ )
{
if (i < A.size()) t += A[i] * b;
C.push_back(t % 10);
t /= 10;
}
return C;
}
vector<int> add(vector<int> &A, vector<int> &B)
{
if (A.size() < B.size()) return add(B, A);
vector<int> C;
int t = 0;
for (int i = 0; i < A.size(); i ++ )
{
t += A[i];
if (i < B.size()) t += B[i];
C.push_back(t % 10);
t /= 10;
}
if (t) C.push_back(t);
return C;
}
int main(){
ss.insert('a');
ss.insert('e');
ss.insert('i');
ss.insert('o');
ss.insert('u');
ss.insert('y');
long long t;
scanf("%lld",&t);
long long pp = 1;
while(t--){
int p; // 1表示辅音, 0 代表 元音
char st[10001];
scanf("%s",st);
int x = 0;
int y = 0;
int qq = 0;
int n = strlen(st);
for (int i = 0; i < n; i++){
if (st[i] != '?'){
y = i;
x = 1;
break;
}
}
if (x == 0){
vector <int> c;
c.push_back(1);
for (int i = 0 ; i < strlen(st); i++){
if (i % 2 == 0)
c = mul(c,20);
else{
c = mul(c,6);
}
}
vector <int> d;
d.push_back(1);
for (int i = 0; i < strlen(st); i ++){
if (i % 2 == 0){
d = mul(d,6);
}
else{
d = mul(d,20);
}
}
c = add(c,d);
printf("String #%lld: ",pp);
for (int i = c.size() - 1 ; i >= 0 ; i--){
printf("%d",c[i]);
}
printf("\n");
}
else{
// y
vector <int> c;
c.push_back(1);
int q = 0;
if (ss.count(st[y]) == 0){ // p = 1是 辅音
p = 1;
q = 1;
}
else{
p = 0;
q = 0;
}
for (int i = y + 1; i < strlen(st); i++){
if (st[i] == '?'){
if (p == 1){
p = 0;
c = mul(c,6);
}
else{
p = 1;
c = mul(c,20);
}
}
else{
if (ss.count(st[i]) == 0){
if( p == 1){
qq = 1;
break;
}
else{
p = 1;
continue;
}
}
else{
if (p == 0){
qq = 1;
break;
}
else{
p = 0;
continue;
}
}
}
}
for (int i = y - 1; i >= 0;i--){
if (st[i] == '?'){
if (q == 1){
q = 0;
c = mul(c,6);
}
else{
q = 1;
c = mul(c,20);
}
}
else{
if (ss.count(st[i]) == 0){
if (q == 1){
qq = 1;
break;
}
else{
q = 1;
continue;
}
}
else{
if (q == 0){
qq = 1;
break;
}
else{
q = 0;
continue;
}
}
}
}
if (qq == 1){
printf("String #%lld: 0\n",pp);
}
else{
printf("String #%lld: ",pp);
for (int i = c.size() - 1; i >= 0; i --){
printf("%d",c[i]);
}
printf("\n");
}
}
pp++;
printf("\n");
}
return 0;
}
G题 解题思路:
首先给予 a, n,代表个数和图的大小,我们可以想,一个数可以从左上角到右下角,必须有一条路径,所以我们可以存入的数量是(n - 1)* (n - 1),因此用a 与 (n - 1)* (n - 1) + 1的大小,如果 大于,那么impossible,然后另外的情况就是 a * (n - 1) * 2 ,其实( n - 1) * 2 就是路径的长度。
#include
#include
#include
using namespace std;
char ans[10][10];
int main(){
int t;
scanf("%d",&t);
for (int i = 1; i <= t; i++){
int a, n;
scanf("%d%d",&a,&n);
if (a > (n - 1)*(n - 1) + 1){
printf("Grid #%d: impossible\n",i);
}
else{
printf("Grid #%d: %d\n",i,a * (2 * (n - 1)));
}
printf("\n");
}
return 0;
}
H题 解题思路:
首先我的思路是从第二行到倒数第二行排着判断上面的点是否是#,如果是#那么我们肯定要对当前的位置进行盖章,所以排着遍历,注意边界的值,然后完美wa掉。(因为其中有些情况不太好确定)
正常的是搜索,我们搜索#点,但是同时我们应该处理边界的情况。
大体思路,dfs,我们从2 ,2 开始搜索,判断十字章的位置是否能够改变,然后求出最小值,最后进行些剪枝,最后我们输出即可。
#include
#include
#include
#include
#include
using namespace std;
const int N = 100010;
char g[10][10]; // 存储点
int mi, n, m;
void dfs(int x, int y, int ans, int res){ // ans 已经点了多少,res 指还剩多少点
if (res == 0){
mi = min(ans,mi);
return ;
}
if((res - 1)/5 + 1 + ans >= mi) return ; // 如果当前走过的点 + 还需要最少走的点 已经超过了最小值
if (x <= 1 || x >= n || y <= 1 || y >= m) return ; // 边界值处理
char tp[7]; // 存储5个需要改变的点
tp[0] = g[x - 1][y];tp[1] = g[x][y];
tp[2] = g[x + 1][y];
tp[3] = g[x][y - 1];
tp[4] = g[x][y + 1];
int num = 0;
int p = 1;
for (int i = 0; i < 5; i++){ // 判断是否有不可改变的点
if (tp[i] == '#') num++;
if (tp[i] == '.') p = 0;
}
if (p && num){
g[x][y] = g[x - 1][y] = g[x + 1][y] = g[x][y + 1] = g[x][y - 1] = '@'; // 让以后印章的位置也可以选取当下点
if (y + 1 < m) dfs(x,y + 1, ans + 1, res - num);
else dfs (x + 1,2, ans + 1, res - num);
g[x - 1][y] = tp[0]; // 回溯 ,还原现场 (这个地方要还原为原本需要改变的点,不能直接变为'.')
g[x][y] = tp[1];
g[x + 1][y] = tp[2];
g[x][y - 1] = tp[3];
g[x][y + 1] = tp[4];
if (x == 2 || x == n - 1 || y == 2 || y == m - 1) return ; // 如果当前是边界值,那么不需要再进行不涂,不然肯定存在涂不到的点
}
if (y + 1 < m) dfs(x,y + 1, ans , res);
else dfs (x + 1,2, ans, res);
return ;
}
int main(){
int t;
scanf("%d",&t);
for (int k = 1; k <= t; k ++){
mi = 2e9;
scanf("%d%d",&n, &m);
int res = 0;
for (int i = 1; i <= n; i ++){
for (int j = 1; j <= m; j++){
cin>>g[i][j];
if (g[i][j] == '#') res ++;
}
}
dfs(2,2,0,res);
if (g[1][1] == '#' || g[1][m] == '#' || g[n][1] == '#' || g[n][m] == '#' || mi == 2e9){
printf("Image #%d: impossible\n",k);
printf("\n");
continue;
}
printf("Image #%d: %d\n",k,mi);
printf("\n");
}
return 0;
}