第六次csp—ccf认证总结

总结:

前几次的认证考试都是最后一题困难其他的没啥难度。

值得一提的是第三题画图的坐标转换和一些细节要注意。第四题的送货对欧拉回路的理解要深刻一点,用了并查集处理。第五题依旧不会,bitsit完全没概念。。

题解: 

数位之和

问题描述

  给定一个十进制整数n,输出n的各位数字之和。

输入格式

  输入一个整数n

输出格式

  输出一个整数,表示答案。

样例输入

20151220

样例输出

13

样例说明

  20151220的各位数字之和为2+0+1+5+1+2+2+0=13。

评测用例规模与约定

  所有评测用例满足:0 ≤ n ≤ 1000000000。

代码:

#include<bits/stdc++.h>
using namespace std;
int n;
void solve()
{
    cin>>n;
    int ans=0;
    while(n){
        int m=n%10;
        n/=10;
        ans+=m;
    }
    cout<<ans;
}
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0),cout.tie(0);
    int t=1;
    while(t--){
        solve();
    }return 0;
}

消除类游戏

问题描述

  消除类游戏是深受大众欢迎的一种游戏,游戏在一个包含有nm列的游戏棋盘上进行,棋盘的每一行每一列的方格上放着一个有颜色的棋子,当一行或一列上有连续三个或更多的相同颜色的棋子时,这些棋子都被消除。当有多处可以被消除时,这些地方的棋子将同时被消除。
  现在给你一个nm列的棋盘,棋盘中的每一个方格上有一个棋子,请给出经过一次消除后的棋盘。
  请注意:一个棋子可能在某一行和某一列同时被消除。

输入格式

  输入的第一行包含两个整数nm,用空格分隔,分别表示棋盘的行数和列数。
  接下来n行,每行m个整数,用空格分隔,分别表示每一个方格中的棋子的颜色。颜色使用1至9编号。

输出格式

  输出n行,每行m个整数,相邻的整数之间使用一个空格分隔,表示经过一次消除后的棋盘。如果一个方格中的棋子被消除,则对应的方格输出0,否则输出棋子的颜色编号。

样例输入

4 5
2 2 3 1 2
3 4 5 1 4
2 3 2 1 3
2 2 2 4 4

样例输出

2 2 3 0 2
3 4 5 0 4
2 3 2 0 3
0 0 0 4 4

样例说明

  棋盘中第4列的1和第4行的2可以被消除,其他的方格中的棋子均保留。

样例输入

4 5
2 2 3 1 2
3 1 1 1 1
2 3 2 1 3
2 2 3 3 3

样例输出

2 2 3 0 2
3 0 0 0 0
2 3 2 0 3
2 2 0 0 0

样例说明

  棋盘中所有的1以及最后一行的3可以被同时消除,其他的方格中的棋子均保留。

评测用例规模与约定

  所有的评测用例满足:1 ≤ nm ≤ 30。

代码:

#include<bits/stdc++.h>
using namespace std;
const int N=35;
int g[N][N];
bool st[N][N];
int n,m;
void solve()
{
    cin>>n>>m;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            cin>>g[i][j];
        }
    }
   for(int i=1;i<=n;i++){
       int o=g[i][1];
       int cnt=1;
       queue<int>q;
       q.push(1);
       for(int j=2;j<=m;j++){
           if(g[i][j]==o){
               cnt++;
               q.push(j);
           }else{
               o=g[i][j];
               cnt=1;
               while(q.size()){
                   q.pop();
               }
               q.push(j);
           }
           if(cnt>=3){
               while(q.size()){
                   int t=q.front();
                   q.pop();
                   st[i][t]=true;
               }
           }
       }
   }
   for(int j=1;j<=m;j++){
       int o=g[1][j];
       int cnt=1;
       queue<int> q;
       q.push(1);
       for(int i=2;i<=n;i++){
           if(g[i][j]==o){
               cnt++;
               q.push(i);
           }else{
               o=g[i][j];
               cnt=1;
               while(q.size()){
                   q.pop();
               }
               q.push(i);
           }
           if(cnt>=3){
               while(q.size()){
                   int t=q.front();
                   q.pop();
                   st[t][j]=true;
               }
           }
       }
   }
   for(int i=1;i<=n;i++){
       for(int j=1;j<=m;j++){
           if(st[i][j]){
               cout<<"0 ";
           }else{
               cout<<g[i][j]<<" ";
           }
       }
       cout<<endl;
   }
}

int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0),cout.tie(0);
    int t=1;
    while(t--){
        solve();
    }return 0;
}

画图

问题描述

  用 ASCII 字符来画图是一件有趣的事情,并形成了一门被称为 ASCII Art 的艺术。例如,下图是用 ASCII 字符画出来的 CSPRO 字样。
  ..____.____..____..____...___..
  ./.___/.___||.._.\|.._.\./._.\.
  |.|...\___.\|.|_).|.|_).|.|.|.|
  |.|___.___).|..__/|.._.<|.|_|.|
  .\____|____/|_|...|_|.\_\\___/.
  本题要求编程实现一个用 ASCII 字符来画图的程序,支持以下两种操作:
   画线:给出两个端点的坐标,画一条连接这两个端点的线段。简便起见题目保证要画的每条线段都是水平或者竖直的。水平线段用字符 - 来画,竖直线段用字符 | 来画。如果一条水平线段和一条竖直线段在某个位置相交,则相交位置用字符 + 代替。
   填充:给出填充的起始位置坐标和需要填充的字符,从起始位置开始,用该字符填充相邻位置,直到遇到画布边缘或已经画好的线段。注意这里的相邻位置只需要考虑上下左右 4 个方向,如下图所示,字符 @ 只和 4 个字符 * 相邻。
  .*.
  *@*
  .*.

输入格式

  第1行有三个整数mnqmn分别表示画布的宽度和高度,以字符为单位。q表示画图操作的个数。
  第2行至第q + 1行,每行是以下两种形式之一:
   0 xyxy2:表示画线段的操作,(x1, y1)和(x2, y2)分别是线段的两端,满足要么x1 = x2 且y1 ≠ y2,要么 y1 = y2 且 x1 ≠ x2。
   1 x y c:表示填充操作,(xy)是起始位置,保证不会落在任何已有的线段上;c 为填充字符,是大小写字母。
  画布的左下角是坐标为 (0, 0) 的位置,向右为x坐标增大的方向,向上为y坐标增大的方向。这q个操作按照数据给出的顺序依次执行。画布最初时所有位置都是字符 .(小数点)。

输出格式

  输出有n行,每行m个字符,表示依次执行这q个操作后得到的画图结果。

样例输入

4 2 3
1 0 0 B
0 1 0 2 0
1 0 0 A

样例输出

AAAA
A--A

样例输入

16 13 9
0 3 1 12 1
0 12 1 12 3
0 12 3 6 3
0 6 3 6 9
0 6 9 12 9
0 12 9 12 11
0 12 11 3 11
0 3 11 3 1
1 4 2 C

样例输出

................
...+--------+...
...|CCCCCCCC|...
...|CC+-----+...
...|CC|.........
...|CC|.........
...|CC|.........
...|CC|.........
...|CC|.........
...|CC+-----+...
...|CCCCCCCC|...
...+--------+...
................

评测用例规模与约定

  所有的评测用例满足:2 ≤ mn ≤ 100,0 ≤ q ≤ 100,0 ≤ x < mx表示输入数据中所有位置的x坐标),0 ≤ y < ny表示输入数据中所有位置的y坐标)。

代码:

#include<bits/stdc++.h>
using namespace std;
const int N = 100;
typedef pair<int, int>PII;
int n, m, q;
bool st[N][N], sst[N][N];
int  id[N][N];
bool st1[N][N];
int dx[] = { 1,-1,0,0 };
int dy[] = { 0,0,1,-1 };
void bfs(int a, int b, int c) {
    memset(st1, false, sizeof(st1));
    queue<PII>q;
    q.push({ a,b });
    st1[a][b] = true;
    while (q.size()) {
        auto t = q.front();
        q.pop();
        int x = t.first;
        int y = t.second;
        for (int i = 0;i < 4;i++) {
            int sx = x + dx[i];
            int sy = y + dy[i];
            if (st[sx][sy] || sst[sx][sy]) {
                continue;
            }if (st1[sx][sy]) {
                continue;
            }if (sx<0 || sx>m || sy<0 || sy>n) {
                continue;
            }
            q.push({ sx,sy });
            st1[sx][sy] = true;
        }
    }
    for (int i = 0;i < m;i++) {
        for (int j = 0;j < n;j++) {
            if (st1[i][j]) {
                id[i][j] = c;
            }
        }
    }
}
void solve()
{
    cin >> m >> n >> q;
    for (int i = 1;i <= q;i++) {
        int k;
        cin >> k;
        if (k == 0) {
            int x1, x2, y1, y2;
            cin >> x1 >> y1 >> x2 >> y2;
            if (x1 == x2) {
                if (y1 < y2) {
                    for (int j = y1;j <= y2;j++) {
                        st[x1][j] = true;
                    }
                }
                else {
                    for (int j = y2;j <= y1;j++) {
                        st[x1][j] = true;
                    }
                }
                
            }
            else if (y1 == y2) {
                if (x1 < x2) {
                    for (int j = x1;j <= x2;j++) {
                        sst[j][y1] = true;
                    }
                }
                else {
                    for (int j = x2;j <= x1;j++) {
                        sst[j][y1] = true;
                    }
                }
                
            }
        }
        else {
            int x, y;
            char c;
            cin >> x >> y >> c;
            if (st[x][y] || sst[x][y]) {
                continue;
            }
            int z = c;
            bfs(x, y, z);
        }
    }
    for (int j = n - 1;~j;j--) {
        for (int i = 0;i < m;i++) {
            if (st[i][j] && sst[i][j]) {
                cout << "+";
            }
            else if (st[i][j] && !sst[i][j]) {
                cout << "|";
            }
            else if (sst[i][j] && !st[i][j]) {
                cout << "-";
            }
            else {
                if (!id[i][j]) {
                    cout << ".";
                }
                else {
                    char c = id[i][j];
                    cout << c;
                }
            }
        }
        cout << endl;
    }

}

int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0), cout.tie(0);
    int t = 1;
    while (t--) {
        solve();
    }return 0;
}

送货

问题描述

  为了增加公司收入,F公司新开设了物流业务。由于F公司在业界的良好口碑,物流业务一开通即受到了消费者的欢迎,物流业务马上遍及了城市的每条街道。然而,F公司现在只安排了小明一个人负责所有街道的服务。
  任务虽然繁重,但是小明有足够的信心,他拿到了城市的地图,准备研究最好的方案。城市中有n个交叉路口,m条街道连接在这些交叉路口之间,每条街道的首尾都正好连接着一个交叉路口。除开街道的首尾端点,街道不会在其他位置与其他街道相交。每个交叉路口都至少连接着一条街道,有的交叉路口可能只连接着一条或两条街道。
  小明希望设计一个方案,从编号为1的交叉路口出发,每次必须沿街道去往街道另一端的路口,再从新的路口出发去往下一个路口,直到所有的街道都经过了正好一次。

输入格式

  输入的第一行包含两个整数nm,表示交叉路口的数量和街道的数量,交叉路口从1到n标号。
  接下来m行,每行两个整数ab,表示和标号为a的交叉路口和标号为b的交叉路口之间有一条街道,街道是双向的,小明可以从任意一端走向另一端。两个路口之间最多有一条街道。

输出格式

  如果小明可以经过每条街道正好一次,则输出一行包含m+1个整数p1, p2, p3, ..., pm+1,表示小明经过的路口的顺序,相邻两个整数之间用一个空格分隔。如果有多种方案满足条件,则输出字典序最小的一种方案,即首先保证p1最小,p1最小的前提下再保证p2最小,依此类推。
  如果不存在方案使得小明经过每条街道正好一次,则输出一个整数-1。

样例输入

4 5
1 2
1 3
1 4
2 4
3 4

样例输出

1 2 4 1 3 4

样例说明

  城市的地图和小明的路径如下图所示。

样例输入

4 6
1 2
1 3
1 4
2 4
3 4
2 3

样例输出

-1

样例说明

  城市的地图如下图所示,不存在满足条件的路径。

评测用例规模与约定

  前30%的评测用例满足:1 ≤ n ≤ 10, n-1 ≤ m ≤ 20。
  前50%的评测用例满足:1 ≤ n ≤ 100, n-1 ≤ m ≤ 10000。
  所有评测用例满足:1 ≤ n ≤ 10000,n-1 ≤ m ≤ 100000。

代码:

#include <bits/stdc++.h>
using namespace std;

const int N = 10010;
int n,m;
set<int> g[N];
int p[N];
int ans[100010],top;

int find(int x)  // 并查集
{
    if (p[x] != x) p[x] = find(p[x]);
    return p[x];
}

void dfs(int u){
    while(g[u].size()){
        int t=*g[u].begin();
        g[u].erase(t),g[t].erase(u);
        dfs(t);
    }
    ans[++top]=u;
}

int main()
{
    scanf("%d%d", &n, &m);
    for(int i=1;i<=n;i++) p[i]=i;

    while(m--){
        int a,b;
        scanf("%d%d",&a,&b);
        g[a].insert(b),g[b].insert(a);
        p[find(a)]=find(b);
    }

    int s=0;
    for(int i=1;i<=n;i++){
        if(find(i)!=find(1)){
            puts("-1");
            return 0;
        }
        else if(g[i].size()%2) s++;
    }

    if(s!=0&&s!=2||s==2&&g[1].size()%2==0){
        puts("-1");
        return 0;
    }

    dfs(1);

    for(int i=top;i;i--) printf("%d ",ans[i]);

    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值