吉首大学第九届"新星杯"大学生程序设计大赛(重现赛)(回顾补题)

本文回顾了一场比赛的经历,总结了未能达成目标的原因,并详细解析了包括DFS、暴力搜索、二分查找、模拟、最长连续子序列等算法的实现代码。

这次比赛6/13,可惜可惜,差一题就达到既定目标,自身思想出了问题,没🧠没♥

官方题解

A 被诅咒的WWT

百思不得正解,于是开始暴力,直接DFS,发现直接超时。赛后看人代码,发现五重循环,其实就是扩展,层层遍历元素然后作出相应操作最后判定有没有结果,%%%代码。学会了新的暴力手法。

#include <bits/stdc++.h> 
using namespace std;
set<long long> s[13];
int main() {
    long long x, y, z;
    int q;
    scanf("%lld%lld%lld%d",&x,&y,&z,&q);
	s[0].insert(0);
    for (int i = 1; i <= 12; ++i) {
        for (auto it:s[i - 1]) {
            s[i].insert(it + x);
            s[i].insert(it - x);
            s[i].insert(it + y);
            s[i].insert(it - y);
            s[i].insert(it + z);
            s[i].insert(it - z);
        }
    }
    long long st = 0, d;
    while (q--) {
        long long ed;
        scanf("%lld", &ed);
        d = ed - st;
        if (s[12].count(d)) {
            puts("YES");
            st = abs(d);
        } else {
            st = 0;
            puts("NO");
        }
    }
}

B Y 老师的井字窗

模拟,行列调换的时候细心一点就行。

#include<bits/stdc++.h>
using namespace std;
vector<vector<int> > num;
vector<int> temp;
int main() {
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=0;i<n;i++) {
        temp.clear();
        temp.resize(m);
        for(int j=0;j<m;j++)
            scanf("%d",&temp[j]);
        num.push_back(temp);
    }
    long long maxn1=-1;
    for(int i=0;i<n;i++) {
        long long sum=0;
        for(int j=0;j<m;j++) {
            sum+=num[i][j];
        }
        maxn1=max(maxn1,sum);
    }
    for(int i=0;i<m;i++) {
        long long sum=0;
        for(int j=0;j<n;j++)
            sum+=num[j][i];
        maxn1=max(maxn1,sum);
    }
    printf("%lld\n",maxn1);
    return 0;
}

C 始战

只会在第一天扩展,之后不再扩张。看错题的我以为是个多源BFS当场去世......其实很简单了,直接每个点扩张上下左右四点,然后看哪个点存在两次标记即为冲突点

#include<bits/stdc++.h>
using namespace std;
char mp[105][105];
int main()
{
    int n, m;
    while (cin >> n >> m)
    {
        memset(mp, '\0', sizeof(mp));
        int flag = 0;
        for (int i = 1; i <= n; i++)
            scanf("%s", mp[i] + 1);
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= m; j++) {
                if (mp[i][j] == '*') {
                    int sum = 0;
                    if (mp[i][j - 1] == '#')
                        sum++;
                    if (mp[i - 1][j] == '#')
                        sum++;
                    if (mp[i + 1][j] == '#')
                        sum++;
                    if (mp[i][j + 1] == '#')
                        sum++;
                    if (sum >= 2)
                    {
                        flag = 1;  printf("%d %d\n", i, j);
                    }
                }
            }
        }
        if(flag==0)
            printf("-1\n");
    }
    return 0;
}

D 秒速五厘米

又是一道二分求解最大最小值,又是莫名原因写挂,我当时直接套的板子啊,不说了%%%代码就完事了

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 2e6 + 100;
int n,m;
int a[N];
int cal(int rate)
{
    int t = 0;
    for(int i = 1;i <= n;i ++){
        t += a[i] / rate;
        if(a[i] % rate) t ++;
    }
    return t;
}
int main()
{
    scanf("%d%d",&n,&m);
    int _max = -1;
    for(int i = 1;i <= n; i ++)
        scanf("%d",&a[i]),_max = max(_max,a[i]);
    int low = 1,high = _max, _min = _max;
    while(low <= high){
        int mid = (low + high)>>1;
        int res = cal(mid);
        if(res > m) low = mid + 1;
        else{
            _min = min(_min,mid);
            high = mid - 1;
        }
    }
    printf("%d\n",_min);
    return 0;
}

E 冬天怎么能够没有辣条

这题目拿了一血,嘿嘿嘿,签到题写的快混了个一血

#include<bits/stdc++.h>
using namespace std;
vector<int> p;
int main() {
    int n;
    while(~scanf("%d",&n)) {
        p.resize(n);
        for(int i=0;i<n;i++) {
            scanf("%d",&p[i]);
        }
        sort(p.begin(),p.end());
        cout<<p[n-2]<<" "<<p[1]<<endl;
    }
    return 0;
}

F 陪你去流浪,踏遍那四海八荒

语文差题意都没怎么看懂,不会待补

G 芒砀山的神秘数字

这个毫无思路,待补

H 小李堆积木

2019CCPC网络赛的签到题,分块递归打表都可以,直接上代码了

#include <bits/stdc++.h>
using namespace std;
 
const int maxn = 1024;
char A[maxn][maxn];
 
void Build (void) {
    A[0][0] = '1';
    A[0][1] = '1';
    A[1][0] = '1';
    A[1][1] = '0';
    for (int k = 2; k <= 10; k++) {
        int a = 1 << (k - 1);
        int b = (1 << k) - 1;
        for (int i = 0; i <= a - 1; i++)
            for (int j = a; j <= b; j++)
                A[i][j] = A[i][j - a];
        for (int i = a; i <= b; i++)
            for (int j = 0; j <= a - 1; j++)
                A[i][j] = A[i - a][j];
        for (int i = a; i <= b; i++)
            for (int j = a; j <= b; j++)
                A[i][j] = A[i - a][j - a] == '1' ? '0' : '1';
    }
}
 
int main () {
    Build();
    int kase,k;
    scanf("%d",&kase);
    while (kase--) {
        scanf("%d",&k);
        k--;
        int n=(1 << k) - 1;
        for (int i=0;i<=n;i++) {
            for (int j=n;j>=0;j--) {
                printf("%c",A[i][j]);
                if(j!=0)
                    printf(" ");
            }
            printf("\n");
        }
    }
    return 0;
}

I Y 老师的乐高小镇

其实是二进制,数二进制数中有多少个1,就挂几个灯笼。这题也是个一血,嘿嘿嘿

#include<bits/stdc++.h>
using namespace std;
int main() {
    long long k;
    while(~scanf("%lld",&k)){
        int cnt=0;
        while(k) {
            if(k%2==1)
                cnt++;
            k/=2;
        }
        printf("%d\n",cnt);
    }
    return 0;
}

J 小阳排队

比赛的时候觉得这种问题一般和最长上升子序列的长度或者最长下降子序列的长度,然后白给,果断放了。赛后一看其实就是求一个最长连续的子序列。👴🤮,可惜可惜

#include <bits/stdc++.h>
using namespace std;
const int N=5e5+5;
int a[N],f[N];
inline int read() {
   int s=0,w=1;
   char ch=getchar();
   while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
   while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
   return s*w;
}
int main() {
    int T,n;
    T=read();
    while(T--) {
        n=read();
        for(int i=1;i<=n;i++) {
            a[i]=read(),f[a[i]]=0;
        }
        int ans=0;
        for(int i=1;i<=n;i++) {
            f[a[i]]=f[a[i]-1]+1;
            ans=max(ans,f[a[i]]);
        }
        printf("%d\n",n-ans);
    }
    return 0;
}

K 小阳数数

并查集+map映射,模板题吧,没什么说的,贴了模板就A了

#include<bits/stdc++.h>
using namespace std;
const int MAXN=1011;
const int MAX_N=1021;
struct node{
    bool vis[11];
};
struct node T[MAXN];
int par[MAX_N];
int rank1[MAX_N];
void init(int n)
{
    for(int i=0;i<=n;i++)
    {
        par[i]=i;
        rank1[i]=0;
    }
}
int find(int x)
{
    if(par[x]==x)
        return x;
    else
    {
        return par[x]=find(par[x]);
    }
}
void unite(int x,int y)
{
    x=find(x);
    y=find(y);
    if(x==y)
        return;
    if(rank1[x]<rank1[y])
        par[x]=y;
    else
    {
        par[y]=x;
        if(rank1[x]==rank1[y])
            rank1[x]++;
    }
}
bool same(int x,int y)
{
    return find(x)==find(y);
}
int main() {
    int t;
    while(~scanf("%d",&t)) {
        while(t--) {
            memset(T,false,sizeof(T));
            int n;
            scanf("%d",&n);
            init(n);
            for(int i=0;i<n;i++) {
                string s;
                cin>>s;
                for(int j=0;j<s.length();j++)
                    T[i].vis[s[j]-'0']=true;
            }
            for(int i=0;i<n;i++) {
                for(int j=i+1;j<n;j++) {
                    for(int k=0;k<=9;k++) {
                        if(T[i].vis[k]==true&&T[j].vis[k]==true) {
                            unite(i,j);
                            break;
                        }
                    }
                }
            }
            int cnt=0;
            for(int i=0;i<n;i++) {
                if(par[i]==i)
                    cnt++;
            }
            printf("%d\n",cnt);
        }
    }
    return 0;
}

L LeeLdler喜欢下棋

不会再见,待补

M 来来来 比比咱谁更聪明

又是一个假博弈,看数据范围可以打表,当瓶子剩余容量为00 时,此时要倒水的人必输,往后递推,如果有人可以倒完水之后达到必输点,那么此点为必赢点,如果没办法倒完水之后达到必输点,则此点也为必输点。然后一直往后递推。

#include<bits/stdc++.h>
using namespace std;
const int MAXN=5011;
bool vis[MAXN];
vector<int> p;
int main() {
    int n,m;
    scanf("%d%d",&n,&m);
    p.resize(m);
    for(int i=0;i<m;i++)
        scanf("%d",&p[i]);
    for(int i=0;i<=n;i++) {
        if(!vis[i]) {
            for(int j=0;j<m;j++)
                vis[i+p[j]]=true;
        }
    }
    if(vis[n])
        puts("Y");
    else
        puts("N");
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值