第十三届西南民族大学程序设计竞赛(同步赛)----整理与补题

原题集点这里

A.《落花》&&《红衣集》
  • 暴力模拟即可
  • 注意边界处特殊处理

code

#include<bits/stdc++.h>

using namespace std;

const int N = 1e5 + 10, inf = 0x3f3f3f3f;
typedef long long ll;

int n, m, t;
ll a[N], b[N];//价格与美丽值

int main()
{
    cin >> n;

    for(int i = 1; i <= n - 1; i ++) cin >> a[i];
    for(int i = 1; i <= n - 1; i ++) cin >> b[i];

    ll ans = a[1];
    int aw = a[1], bw = b[1];
    b[n] = 0, a[n] = inf;
    //避免越界

    for(int i = 2; i <= n - 1; i ++)
    {
        if(b[i] > bw)
        {
            if(b[i + 1] == b[i])
            {
                bw = b[i];
                if(a[i + 1] < a[i]) ans += a[i + 1];
                else ans += a[i];
            }
            else if(b[i] > b[i + 1]) ans += a[i], bw = b[i];
            else ans += a[i + 1], bw = b[i + 1];

            i ++;
        }
    }

    cout << ans << "\n";

    return 0;
}

B.留春春不住,春归人寂寞。
  • 最短路板子题任选一个
  • 弗洛伊德算法还是会时间超限
  • 注意一次性就可以得到从起点到其他各个点的距离(dist数组的实际含义)

code

#include<bits/stdc++.h>

using namespace std;

const int N = 1010, M = 1e6 + 10;

int e[M], ne[M], w[M], idx, h[N];
int dist[N];
bool st[N];
int t, n, m;

void add(int a, int b, int c)
{
    e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx ++;
}

void spfa()
{
    memset(dist, 0x3f, sizeof dist);
    memset(st, 0, sizeof st);
    dist[1] = 0;

    queue<int > q;
    q.push(1);
    st[1] = true;

    while(q.size())
    {
        int t = q.front();
        q.pop();
        st[t] = false;

        for(int i = h[t]; i != -1; i  = ne[i])
        {
            int j = e[i];
            if(dist[j] > dist[t] + w[i])
            {
                dist[j] = dist[t] + w[i];
                if(!st[j])
                {
                    q.push(j);
                    st[j] = true;
                }
            }
        }
    }
}

int main()
{
    cin >> n >> m;
    memset(h, -1, sizeof h);

    while(m --)
    {
        int a, b, c;
        cin >> a >> b >> c;
        add(a, b, c), add(b, a, c);
    }

    spfa();
    cin >> t;

    while(t --)
    {
        int v;
        cin >> v;
        cout << dist[v] << endl;
    }

    return 0;
}

C.厌风风不定,风起花萧索。
  • 利用前缀和的思想降低暴力枚举的时间复杂度
  • 利用map类容器的特性将字符串映射为数字方便操作
  • (比赛时还真没有思路太菜了

code

#include<bits/stdc++.h>

using namespace std;

const int N = 20;

int  n, m, t;
unordered_map<string, int> q;
int a[N][N];//某个字符串到第i天出现了见几次

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);

    cin >> n;

    int cnt = 1;
    for(int i = 1; i <= n; i ++)
    {
        string r;
        int c;
        cin >> r >> c;
        if(!q[r]) q[r] = cnt ++;
        for(int j = 1; j <= cnt; j ++ )
        {
            a[j][i] = a[j][i - 1];
        }
        //将数值向后传递
        a[q[r]][i] += c;
    }

    int t;
    cin >> t;

    while(t --)
    {
        int l, r;
        string s;
        cin >> l >> r >> s;

        cout << a[q[s]][r] - a[q[s]][l -1] << "\n";
    }

    return 0;
}

D.既兴风前叹,重命花下酌。
  • 直接上答案吧(万能的猜想

code

#include<bits/stdc++.h> 

using namespace std; 

int main() 
{ 
    cout << "FTFTTTF" << '\n'; 
    return 0; 
}
E.劝君尝绿醅,教人拾红萼。
  • 少年,以后上课还会水吗[当然]
  • 考察转义字符

code

#include<bits/stdc++.h>

using namespace std;

int main()
{
    puts("\"xi\\nan\\min\\zu\\da\\xue,zhen\\mei!\"");

    return 0;
}

F.桃飘火焰焰,梨堕雪漠漠。
  • 当然是先玩最喜欢的游戏啦(小孩子才做选择
  • 当最喜欢的游戏不够的时候再用其他的填数
  • 尽量选择少的

code

#include<bits/stdc++.h>

using namespace std;

typedef long long ll;
const int N = 1e5 + 10, INF = 0x3f3f3f3f;

ll p[N], q[N];
ll t,n,m,k;

int main()
{

	cin>>n>>m>>k;
	ll ans=0;
	for(int i= 1 ; i <= n; i ++) cin >> p[i];
	for(int i = 1; i <= m; i ++)
	{
	    ll u;
		cin >> u;
		ans += p[u];
		p[u] = INF;
		k --;
	}

	sort(p + 1, p + 1 + n);
	for(int i = 1; i <= k; i ++) ans+= p[i];
	cout << ans;

	return 0;
}


G.独有病眼花,春风吹不落。
  • 看到成环,哎嘿,就想到了并查集并不是因为之前做过类似的
  • 只要连线两端属于一个父节点即为可成环
  • 需要把坐标编号

code

#include<bits/stdc++.h>

using namespace std;

const int N = 5e6;

int n, m, t;
int p[N];

int findx(int x)
{
    if(p[x] != x) p[x] = findx(p[x]);
    return p[x];
}

int get_num(int x, int y)
{
    return x * n + y;
}

int main()
{
    cin >> n >> m;
    
    for(int i = 0; i <= n * n; i++) p[i] = i;
    
    int res = 0;
    for(int i = 1; i <= m; i ++)
    {
        int u, v, a, b;
        char c;
        cin >> u >> v >> c;
        u --, v --;
        a = get_num(u, v);
        if(c == 'D')
        {
            b = get_num(u + 1, v);
        }
        else b = get_num(u, v + 1);
        
        int pa = findx(a), pb = findx(b);
        if(pa == pb)
        {
            res = i;
            break;
        }
        p[pa] = pb;
    }
    
    if(res) cout << res << "\n";
    else puts("draw");
    
    return 0;
}

H.荷池堪作镜,盈盈可鉴心。
  • 根据所给递推即可(很神奇)
#include<bits/stdc++.h>

using namespace std;

const int N=1e7+9;
typedef long long ll;

ll arr[N];
int mod=1e9+7;

int main()
{

   ll n;
   cin>>n;
   arr[1]=1,arr[2]=2,arr[3]=3;
   for(int i=4;i<=n;i++)
    {
       arr[i]=(arr[i-1]+arr[i-3])%mod;
   }
    cout<<arr[n];

    return 0;

}

I.荷香堪筑梦,鸳鸯和月寻。
  • 一定要先读懂题意(某个小伙读题都读半天)
  • 也就是说他可以横向移动,一行一行往下下(说的好抽象
  • 然后每次看上一层,在能够到达的范围内是否有空地
  • 依次类推直到最上层

code

#include<bits/stdc++.h>

#define x first
#define y second

using namespace std;

int n, m, a;

const int N = 1010;
typedef pair<int, int> PII;

char g[N][N];
PII q[N];
bool st[N][N];

void bfs(int sx, int sy)
{
    st[sx][sy] = true;
    int hh = 0, tt = 0;
    q[0] = {sx, sy};

    while(hh <= tt)
    {
        auto t = q[hh ++];

        //右半范围
        for(int i = sy; i <= min(sx + a, m - 1); i ++)
        {
            if(t.x == 0)
            {
                puts("yes");
                return;
            }
            if(st[t.x - 1][i] || g[t.x - 1][i] == '*') continue;
            st[t.x - 1][i] = true;
            q[++ tt] = {t.x - 1, i};
        }
        //左半范围
        for(int i = sy; i >= max(sx - a, 0); i --)
        {
            if(t.x == 0)
            {
                puts("yes");
                return;
            }
            if(st[t.x - 1][i] || g[t.x - 1][i] == '*') continue;
            st[t.x - 1][i] = true;
            q[++ tt] = {t.x - 1, i};
        }
    }

    puts("no");

    return;
}

int main()
{
    cin >> n >> m >> a;

    int xx, yy;
    for(int i = 0; i < n; i ++)
        for(int j = 0; j < m; j ++)
        {
            cin >> g[i][j];
            if(g[i][j] == 'a')
            {
                xx = i;
                yy = j;
            }
        }

    bfs(xx, yy);

    return 0;
}


J.荷香莫深湎,终付秋风落。
  • 就很单纯的记录输入的次数
  • 系统会自动跳出(当时过的我也很震惊)

code

#include<bits/stdc++.h>

using namespace std;

int main()
{
    int ans=0;
    string s;
    while(cin>>s)
    {
        for(int i=0;i<s.size();++i)
        {
            if(s[i]==':'&&s[i+1]=='w')
            ans++;
        }
    }
    cout << ans << endl;

    return 0;
}

K.荷香竟深湎,永待盛夏陌。
  • 数据量较小,暴力求解即可
  • 比赛时由于没看数据量顿时以为会是很难的(纸老虎其实)
  • 从大佬博客看到了goto的用法,实在比通过判断出循环要方便
#include<bits/stdc++.h>

using namespace std;

const int N = 1010;

int n, m, t;
int p[N], q[N];

int main()
{
    cin >> t;

    while(t --)
    {
        cin >> p[1] >> p[2] >> p[3] >> p[4];

        for(int i = 0; i < 4; i ++)
            for(int j = 0;j < 4; j ++)
                for(int k = 0; k < 4; k ++)
                    for(int r = 0; r < 4; r ++)
                    {
                        int t = i + j + k + r;
                        q[1] = p[1] + i + j + r;
                        q[2] = p[2] + i + j + k;
                        q[3] = p[3] + j + k + r;
                        q[4] = p[4] + i + k + r;

                        for(int u = 1; u <= 4; u ++)
                        {
                            q[u] %= 4;
                            if(!q[u]) q[u] = 4;
                        }

                        if(q[1] == q[2] && q[2] == q[3] && q[3] == q[4])
                        {
                            cout << t << "\n";
                            while(i --) printf("1 ");
                            while(j --) printf("2 ");
                            while(k --) printf("3 ");
                            while(r --) printf("4 ");
                            goto ed;
                        }
                    }
        ed:;
    }

    return 0;

L.相思子肯来,约在莲花岸。
  • 自己写的纯纯暴力模拟
  • 其实可以一次性求出最大值有最小值
  • 根据类型选择即可减少代码量(比较容易理解姐u不贴过来了才不是懒呢

code

#include<bits/stdc++.h>

using namespace std;

const int N = 10, inf = 0x3f3f3f3f;

int n, m, t;

struct node
{
    int x, y, type;
}zj[N], df[N];

int get_dis(int x1, int z1, int x2, int z2)
{
    return (x1 - x2) * (x1 - x2) + (z1 - z2) * (z1 - z2);
}

int main()
{
    cin >> n >> m;

    for(int i = 0; i < n; i ++)  cin >> zj[i].x >> zj[i].y >> zj[i].type;
    for(int i = 0; i < m; i ++) cin >> df[i].x >> df[i].y >> df[i].type;

    for(int i = 0; i < n; i ++)
    {
        int res = 0;
        int ax = zj[i].x, ay = zj[i].y, aty = zj[i].type;

        if(!aty)
        {
            int minn = inf;
            for(int j = 0; j < m; j ++)
            {
                int bx = df[j].x, by = df[j].y;
                if(get_dis(ax, ay, bx, by) < minn)
                {
                    minn = get_dis(ax, ay, bx, by);
                    res = j;
                }
            }
            cout << res + 1 << " ";
        }

        else
        {
            int maxn = 0;
            for(int j = 0; j < m; j ++)
            {
                int bx = df[j].x, by = df[j].y;
                if(get_dis(ax, ay, bx, by) > maxn)
                {
                    maxn = get_dis(ax, ay, bx, by);
                    res = j;
                }
            }
            cout << res + 1<< " " ;
        }
    }
    puts("");

    for(int i = 0; i < m; i ++)
    {
        int res = 0;
        int ax = df[i].x, ay = df[i].y, aty = df[i].type;

        if(!aty)
        {
            int minn = inf;
            for(int j = 0; j < m; j ++)
            {
                int bx = zj[j].x, by = zj[j].y;
                if(get_dis(ax, ay, bx, by) < minn)
                {
                    minn = get_dis(ax, ay, bx, by);
                    res = j;
                }
            }
            cout << res + 1 << " ";
        }

        else
        {
            int maxn = 0;
            for(int j = 0; j < m; j ++)
            {
                int bx = zj[j].x, by = zj[j].y;
                if(get_dis(ax, ay, bx, by) > maxn)
                {
                    maxn =get_dis(ax, ay, bx, by);
                    res = j;
                }
            }
            cout << res + 1<< " " ;
        }
    }
    puts("");

    return 0;
}


M.潇潇日暮时,掠水鸳鸯散。
  • 纯正的01背包问题
#include<bits/stdc++.h>

using namespace std;
typedef pair<int, int> PII;

const int N = 1010;

int n, m, t;
int v[N], w[N];
int f[N];

int main()
{
    int p;

    cin >> m >> p;

    for(int i = 1; i<= p; i ++) cin >> v[i] >> w[i];

    for(int i = 1; i <= p; i ++)
        for(int j = m; j >= v[i]; j --)
            f[j] = max(f[j], f[j - v[i]] + w[i]);


        cout << f[m] << endl;

        return 0;
}
总结

第一次整理整套题感觉收获了很多,希望以后能继续下去。比赛过程中最大的问题还是心态问题,要稳住,而不是紧张与焦虑。塌下心来尽自己的能力去做就好了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值