日期:2024年10月2日
学号:S14738
一、我的总分:
T1【下棋(chess)】:70分
T2【汪洋(BigWater)】:0分
T3【删数(delnum)】:0分
T4【平分糖果(candy)】:0分
二、比赛概况:
T1【下棋(chess)】:
题目不算很难,有思路,也实现出来了,但是忽略了数据大小应该用long long,所以只得了70分,最后的30%数据应该是比较大。
T2【汪洋(BigWater)】:
感觉是要用dfs解决,写完调试的时候发现不太行,可能是死循环了,具体没看出来,然后就直接cout了,最后也是没时间再思考了。
T3【删数(delnum)】:
感觉需要暴力枚举,但是数据太大了(谁会在数据最大10^9的时候暴力枚举),所以我先判断一下有没有删连续数列的,这样的会好算一些,关键是没有……所以就0分了。
T4【平分糖果(candy)】:
时间不太够了,也没再仔细读题,觉得美味程度如果是奇数个就不行,简单蒙了一点代码,也没对,应该是格式的问题吧。
三、比赛分析:
T1【下棋(chess)】:
1、题目大意
Meowowco 最近沉迷下棋。
众所周知,棋盘上一局有 n 个玩家一起游戏。
我们的棋子称为”英雄”,英雄分为1、2、3星。1 个 3 星英雄可以由 3 个 2 星英雄合成,1 个 2 星英雄可以由 3 个 1 星英雄合成。
现在给出每名玩家的英雄阵容,我们定义阵容强度为 18x + 3y + z,其中 x 为 3 星英雄个数,y 为两星英雄个数,zz 为一星英雄个数,其中可以用低星英雄合成高星英雄后再计算阵容强度。
根据玩家的阵容强度,将玩家序号进行排序,并按阵容强度从大到小的顺序输出玩家的序号(若阵容强度相同,则把玩家序号(第i个输入的玩家序号为i)小的排在前面)。
2、考试思路
输入 -> 分别计算1、2、3星英雄个数(运用 % 和 / ) -> 排序 -> 输出
3、讲解后思路
和我的思路差不多,只不过变量和结构体都要用long long类型
4、AC代码
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
//必须用 long long 类型,没有用就会像我一样得 70分
long long n;
struct node{
long long i,str;
}ply[100005];
//sort函数
bool cmp(node a,node b){
//题目要求阵容强度从大到小排序,阵容强度相同则把序号小的排在前面
if(a.str == b.str){
return a.i < b.i;
}
return a.str > b.str;
}
int main(){
// freopen("chess.in","r",stdin);
// freopen("chess.out","w",stdout);
cin >> n;
for(int j = 1;j <= n;j++){
long long x,y,z;
cin >> z >> y >> x;
//1个3星英雄可以由3个2星英雄合成
y+=z/3;
z%=3;
//1个2星英雄可以由3个1星英雄合成
x+=y/3;
y%=3;
ply[j].i = j;
//计算阵容强度
ply[j].str = x*18+y*3+z;
}
//排序
sort(ply+1,ply+1+n,cmp);
for(int j = 1;j <= n;j++){
cout << ply[j].i << " ";
}
// fclose(stdin);
// fclose(stdout);
return 0;
}
T2【汪洋(BigWater)】:
1、题目大意
Meowowco 连夜坐飞机去参加上海国家会展中心的 BilibiliWorld 2023,可是到现场时,已经是一片汪洋。。。
就算是这样,Meowowco 也不算白来一趟,因为场馆里还有许多可爱的 coser,她可以和这些coser一起合影,然后发说说羡慕她那可怜的队友。
场馆可以看成一张由n×n个格子构成的矩阵。场馆内的格子可能被水淹没,Meowowco趟水走过去可能会影响心情,因此这些格子上的值为 负数。但是另外的一些格子上站着可爱的 coser,如果 Meowowco 可以与那些 coser合影,那么她就会变得开心,因此这些格子的值为 正数。
Meowowco 最开始的心情为 100 点,她在逛 BW 的过程中:
如果走到值为正数的格子,说明可以和可爱的coser拍照,因此会增加心情。
如果走到值为负数的格子,说明Meowowco需要趟水,因此心情值会下降。
Meowowco 从 (1,1) 点向右出发,即朝 (1,2)点出发,她每次移动只能移动到一个相邻的格子,并且她需要按照下面的路线逛一圈:
沿着上一步的方向继续移动
进行顺时针 90 度转向(注意不可以在同一个格子内连续转向)
不再逛那些逛过的格子(除了起点)
其中转向指的是:如果上一步向右走,那么转向之后则为向下走;如果上一步向左走,那么转向之后则为向上走……
那么逛完 BW 之后,肯定是要从 (1,1) 点离开然后回家的,那么问题来了,Meowowco离开时心情值最大是多少。
2、考试思路
感觉要用dfs吧,没什么明确的思路
3、讲解后思路
由于规定了转向,所以Meowowco的路线应该是一个矩形,具体思路如下:
输入 -> 计算行列前缀和 -> 枚举答案 -> 输出
4、AC代码
#include<iostream>
#include<cstdio>
using namespace std;
const int N = 1e3+5;
int n,a[N][N],row[N][N],col[N][N],ans;
int main(){
// freopen("BigWater.in","r",stdin);
// freopen("BigWater.out","w",stdout);
cin >> n;
for(int i = 1;i <= n;i++){
for(int j = 1;j <= n;j++){
cin >> a[i][j];
//计算行列前缀和
row[i][j] = row[i][j-1]+a[i][j];
col[i][j] = col[i-1][j]+a[i][j];
}
}
for(int i = 1;i <= n;i++){
for(int j = 1;j <= n;j++){
//比较 ans和矩形四边长度和,记得减去重复的四个点
ans = max(ans,row[1][j]+row[i][j]+col[i][1]+col[i][j]-a[1][j]-a[i][1]-a[1][1]-a[i][j]);
}
}
cout << ans+100;
// fclose(stdin);
// fclose(stdout);
return 0;
}
T3【删数(delnum)】:
1、题目大意
有一个集合,初始状态里面有数字 1、2、3、4、5……114514^1919810,你可以理解为很多正整数。
现在给你一个长度为 n 数组a (1≤ai≤10^9 ),每次操作将当前集合中第 a1小、第a2小……第an小的数同时移除。
现在有 q 次询问,每次询问包含一个整数 x,查询从初始状态到删除 x 需要操作多少次。若无法删除,输出 0。
2、考试思路
我不会啊,所以纯蒙代码
3、讲解后思路
输入 -> 删除比x小的并判断x该不该删除 -> 输出
4、AC代码
#include<iostream>
#include<cstdio>
using namespace std;
long long n,q,a[100005];
long long fun(long long x){
long long ans = 0;
//找到第一个大于等于x的数
long long idx = lower_bound(a+1,a+1+n,x)-a;
//没找到就从n开始计算
//找到了但不是x就从idx-1开始计算
if(idx == n+1 || a[idx] != x){
idx--;
}
for(int i = idx;i >= 1;i--){
if(x < a[i]){
continue;
}
//如果刚好到 a[i] 一定能够删除
if((x-a[i])%i == 0){
return ans+(x-a[i])/i+1;
}
long long num = (x-a[i])/i+1;
ans+=num;
x-=num*i;
}
return -1;
}
int main(){
// freopen("delnum.in","r",stdin);
// freopen("delnum.out","w",stdout);
cin >> n;
for(int i = 1;i <= n;i++){
cin >> a[i];
}
cin >> q;
while(q--){
long long x;
cin >> x;
long long ans = fun(x);
//若无法删除,输出0
if(ans == -1){
cout << 0;
}else{
cout << ans;
}
cout << endl;
}
// fclose(stdin);
// fclose(stdout);
return 0;
}
T4【平分糖果(candy)】:
1、题目大意
小可的妈妈给了小可很多的糖果,已经糖果都有美味程度,美味程度用1~6的整数表示。
有一天达达来小可家做客,小可要把糖果分给达达,现在已知了美味程度为 i 的糖果有 a[i] 个,请问小可能不能把糖果平分成美味程度之和相同的两部分。
2、考试思路
我还是不太会啊,也就只能蒙代码
3、讲解后思路
这道题是动规,也就是dp,但是我没学过啊啊啊
输入 -> 计算美味程度之和 -> 判断(美味程度之和/2)是否能被组成 -> 输出
4、AC代码
#include<iostream>
#include<cstdio>
using namespace std;
long long a[10],cnt;
bool dp[200005];
bool pd(){
//计算美味程度总和
long long m = a[1]+a[2]*2+a[3]*3+a[4]*4+a[5]*5+a[6]*6;
//如果美味程度总和是奇数,则不可能平分成两个整数
if(m%2 == 1){
return false;
}
m/=2;
for(int i = 0;i <= m;i++){
dp[i] = false;
}
dp[0] = true;
//for循环判断美味程度总和 dp[j]是否能被构成
for(int t = 1;t <= 6;t++){
for(int i = 1;i <= a[t];i*=2){
for(int j = m;j >= i*t;j--){
dp[j] = dp[j] || dp[j-i*t];
}
if(dp[m]){
return true;
}
}
}
return false;
}
int main(){
// freopen("candy.in","r",stdin);
// freopen("candy.out","w",stdout);
while(cin >> a[1]){
for(int i = 2;i <= 6;i++){
cin >> a[i];
}
if(a[1]+a[2]+a[3]+a[4]+a[5]+a[6] == 0){
break;
}
cnt++;
cout << "Collection #"<< cnt << ":" << endl;
//按照题目要求输出,记住有两次换行
if(pd()){
cout << "Can be divided." << endl << endl;
}else{
cout << "Can't be divided." << endl << endl;
}
}
// fclose(stdin);
// fclose(stdout);
return 0;
}
四、反思&总结:
和上次一样,嗯…就是数组、变量、结构体什么的尽量开大,注意数据大小是否要用long long类型,最后检查一下输出。