课程设计CCF

http://118.190.20.162/home.page

小明种苹果

题意:n棵树,m次操疏果操作。\(a_{i0}表示第i颗初始苹果数量,a_{ij}(1<=j<=m)表示第i棵树第j次疏果,其绝对值为疏果数量\)
求疏果完毕后树上苹果所剩总数,疏果数最多的编号如果存在相等疏果数输出编号较小的苹果树,该树疏果数量。
解法:第一问:苹果所剩总数只需将n*m+1内矩阵的数全部相加
第二问和第三问:创建结构体数组成员为疏果数量和该棵树编号,统计相关信息进行,以疏果数量为第一关键字标号为第二关键字排序。排序完后第一数组元素即为答案。

const int maxn = 1e3+9;

struct node{
    int num , id ;//第i棵树疏果数和编号
}a[maxn];

bool cmp(node a , node b){//以疏果数为第一关键字,编号为第二关键字排序
    if(a.num != b.num) return a.num > b.num;
    return a.id < b.id;
}

void solve(){
    int n , m , sum = 0 ;
    scanf("%lld%lld" , &n , &m);
    rep(i , 1 , n){
        int x ;
        scanf("%lld" , &x);
        sum += x ;
        a[i].num = 0;
        a[i].id = i ;
        rep(j , 1 , m){
            scanf("%lld" , &x);
            a[i].num -= x ;
            sum += x ;
        }
    }
    sort(a+1 , a+1+n , cmp);
    cout << sum << " " << a[1].id << " " << a[1].num << endl;
}

小明种苹果(续)

题意:n棵树,每棵树有\(m_i\)次操作 , 每次操作如果为正数为记录此时苹果数,负数为疏果数。第一次操作一定为正数,操作过程中不会出现苹果树为负数。所有苹果树为首尾相连的环形。
问:
1、所剩苹果树总数
2、有几棵树的苹果存在非疏果脱离苹果树数量
3、有几个三个相邻的苹果树存在第二个问题的情况

解法:见码

int num[maxn];//记录树上苹果数量
void solve(){
    int n , sum = 0 , ans = 0;
    scanf("%lld" , &n);
    set<int>s;
    rep(i , 1,  n){
        int m ;
        scanf("%lld" , &m);
        scanf("%lld" , &num[i]);//初始值
        rep(j , 2 , m){
            int x ;
            scanf("%lld" , &x);
            if(x < 0){
                num[i] += x ;//疏果后
            }else if(x > 0){
                if(num[i] != x){//如果不等说明出现自动脱离的情况
                    s.insert(i);
                    num[i] = x ;
                }
            }
        }
        sum += num[i];
    }
    if(size(s) < 3){
        cout << sum << " " << size(s) << " " << 0 << endl;
        return ;
    }
    for(auto i : s){//判断相邻三个自动脱离数量
        if(i == 1){
            if(s.count(n) && s.count(2)){
                ans++;
            }
        }else if(i == n){
            if(s.count(1) && s.count(n-1)){
                ans++;
            }
        }else{
            if(s.count(i-1) && s.count(i+1)){
                ans++;
            }
        }
    }
    cout << sum << " " << size(s) << " " << ans << endl;
}

字符画

题意:给出大小为\(n*m\)的图片,每一小格为一个像素,一个像素由三个值(R,G,B)构成,值由0-255的16进制表示,现在需要将这张图片划分成\(q*p\)大小的像素块,求像素块的值为平均值。
如果当前像素块的颜色与前一个像素块的颜色不同,如果为背景色则直接输出转义序列ESC[0m.否则输出更改颜色的转义序列ESC[48;2;R;G;Bm
如果与前一像素块颜色相同则不需要更改颜色。
输入:输入m,n,p,q.接下来\(n*m\)行分别表示一个像素的16进制的表示,如果为#a,则需转化为#aaaaaa.如果为#abc,转为#aabbcc。
输出:全部输出位16进制序列,有\(m*n/p*q\)个空格(即每个像素块后跟一个空格),\(n/q\)有个回车(即每一行的像素块结束输出一个回车)。注意空格与回车都为16进制的转移字符。
考点:十六进制转十进制、数字拆分、十进制转16进制。

const int maxn = 2e3+9;
int c[maxn][maxn][3];//像素点
string s ;
int R , r , G , g , B , b ;
int turn10(char a , char b){//十六进制转为10进制
    return (isalpha(a)?(a-'a'+10):(a-'0'))*16 + (isalpha(b)?(b-'a'+10):(b-'0'));
}

void outchar(int a){//十进制转为十六进制
    printf("\\x%02X" , a);
}
void outstr(string s){//字符串转十六进制
    for(auto i : s){
        outchar(i);
    }
}
void outnum(int i){//数字拆分,转十六进制
    vector<int>v;
    if(i==0)v.pb(i);
    while(i>0) v.pb(i%10) , i/=10;
    for(i = size(v)-1 ; i >= 0 ; i--)outchar('0'+v[i]);
}
void solve(){
    int n , m , p , q , num ;
    cin >> m >> n >> p >> q;
    num = p*q;
    rep(i , 0 , n-1){
        rep(j , 0 , m -1){
            cin >> s;
            if(size(s) == 2){//将#a格式转换为#aaaaaa
                s += string(5 , s[1]);
            }else if(size(s) == 4){//将#abc转为#aabbcc
                s = "#" + string(2 , s[1]) + string(2 , s[2]) + string(2 , s[3]);
            }
            rep(k , 0 , 2){
                c[i][j][k] = turn10(s[k*2+1] , s[k*2+2]);//两两为一组16进制求10进制
            }
        }
    }
    for(int i = 0 ; i < n ; i += q){
        for(int j = 0 ; j < m ; j += p){
            R = G = B = 0 ;
            for(int k = i ; k < i + q ; k++){
                for(int l = j ; l < j + p ; l++){
                    R += c[k][l][0] , G += c[k][l][1] , B += c[k][l][2];//当前像素块的像素和
                }
            }
            R /= num , G /= num , B /= num ;//像素块的平均值
            if(!(R==r&&G==g&&B==b)){//与前一个像素块颜色不同
                if(R==0&&G==0&&B==0){//为默认颜色
                    outstr(string(1,char(27)) + "[0m");//重置转义序列
                }else{//更改颜色
                    outstr(string(1,char(27)) + "[48;2;") , outnum(R),
                    outchar(';'),outnum(G),outchar(';'),outnum(B),outchar('m');
                }
                r = R , g = G , b = B ;//记录前一像素块颜色
            }
            outchar(' ');//mn/pq个空格
        }
        if(R!=0||G!=0||B!=0) outstr(string(1,char(27))+"[0m");//行末判断是否为默认颜色
        r = g = b = 0 ;//转为默认色
        outchar('\n');//n/q个换行
    }
}

推荐系统

题意:m种商品编号0-m-1,初始每类有n件商品,给出编号和分数,任意时刻,同一类商品不存在标号相同的两个商品。共有q次操作,有三种操作:
1、增加新商品
2、删除某一商品
3、一共选出商品数量不超过K个,每一种类选择不超过\(k_i\)个商品。输出在满足条件下,m类分大的编号每一类占一行,不存在输出-1。
解法:一开始写用了重载运算符优先队列,但是因为每次询问都是对后面询问产生影响的,就不好保存数据 , 代码写的很丑。
之后看了下网上的代码,发现使用重载运算符的set(第一次做到重载set的运算符,所以没有想到用set去存数据)。

  • 增加操作:直接使用set插入。
  • 删除操作:因为只给出了商品的种类和编号没有给出分数,所以不好直接set删除数据,所以选择使用二维map将该商品标记(当然可以也去记录商品分数同样需要二维map),使用map只能拿80分,用unordered——map才能拿满分。
    因为map时间复杂度大一些为O(logn),而unordered——map因为不会对数据排序所以时间复杂度低为O(1).
  • 直接遍历set数据,对于标记的直接过掉。
    数据范围:m(<=50),n(<=3e4),id(<=1e9),q(<=1e5),ask3(<=100)
const int maxn = 59;
int k[maxn];
struct node{
    int ty , id , sc;
    bool operator < (const node a)const {
        if(sc != a.sc) return sc > a.sc;//商品分数为第一关键字
        if(ty != a.ty) return ty < a.ty;//类型为第二关键字
        return id < a.id;//标号为第三关键字
    }
    node(int _ty , int _id , int _sc){
        ty = _ty , id = _id , sc = _sc;
    }
    node(){}
};
unordered_map<int , int>vis[maxn];//标记删除商品

void solve(){
    set<node>s;
    int m , n ;
    scanf("%lld%lld" , &m , &n);
    rep(i , 1 , n){
        int x , y ;
        scanf("%lld%lld" , &x , &y);
        rep(j , 0 , m-1){//每一种类都插入标号为x分数为y的商品
            s.insert(node(j , x , y));
        }
    }
    int q ;
    scanf("%lld" , &q);//q次操作
    while(q--){
        int t , x , y , z ;
        scanf("%lld" , &t);
        if(t == 1){
            scanf("%lld%lld%lld" , &x , &y , &z);
            s.insert(node(x , y , z));//新增商品
        }else if(t == 2){
            scanf("%lld%lld" , &x , &y);
            vis[x][y] = 1 ;//标记删除商品
        }else{
            int K ;
            scanf("%lld" , &K);//总共选择不超过K个商品
            vector<int>v[maxn];
            rep(i , 0 , m-1){
                scanf("%lld" , &k[i]);//每一种商品选不超过ki个商品
            }
            int ans = 0 ;
            for(auto i : s){
                if(ans >= K) break;
                if(vis[i.ty][i.id]) continue;
                if(k[i.ty]){
                    v[i.ty].pb(i.id);
                    k[i.ty]--;
                    ans++;
                }
            }
            rep(i , 0 , m-1){
                if(!size(v[i])){
                    printf("-1\n");
                    continue;
                }
                int flag = 0;
                for(auto j : v[i]){
                    if(!flag) printf("%lld" , j) , flag = 1;
                    else printf(" %lld" , j);
                }
                printf("\n");
            }
        }
    }
}

posted @ 2020-06-29 10:58  无名菜鸟1  阅读(219)  评论(0编辑  收藏  举报