CCF 第二题

Posted twomeng

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CCF 第二题相关的知识,希望对你有一定的参考价值。

最小差值 另解

先对数据进行排序,求相邻数据的最小值

打酱油

 1 #include <iostream>
 2 #include <algorithm>
 3 #include <string.h>
 4 #include <string>
 5 #include <stdio.h>
 6 #include <iomanip>
 7 using namespace std;
 8 /*
 9     题目:
10     用时:tomato *
11     思路:
12 */
13 
14 
15 int main()
16 {
17     int n; // n <=300
18     while (cin>>n)
19     {
20         int x = n / 10 ;
21         int five = ( x / 5 ) * 2;
22         int thr = (x % 5) / 3 ;
23         cout << five+thr + x <<endl;
24     }
25 
26 
27     return 0;
28 }

 

工程做法:使用常量为了程序的通用性
/* CCF201709-1 打酱油 */  

#include <stdio.h>  

const int ONE = 1;  
const int TWO = 2;  
const int FIVE = 5;  
const int THREE = 3;  
const int PRICE = 10;  

int main(void)  
{  
    int n, group1, group2, group3;  

    scanf("%d", &n);  

    group1 = n / PRICE / FIVE;  
    group2 = (n - group1 * PRICE * FIVE) / PRICE / THREE;  
    group3 = (n - group1 * PRICE * FIVE - group2 * PRICE * THREE) / PRICE;  

    printf("%d
", group1 * (FIVE + TWO) + group2 * (THREE + ONE) + group3);  

    return 0;  
}  

 

分蛋糕

 1 #include <iostream>
 2 #include <algorithm>
 3 #include <string.h>
 4 #include <string>
 5 #include <stdio.h>
 6 #include <iomanip>
 7 using namespace std;
 8 /*
 9     题目:分蛋糕
10     思路:
11 */
12 
13 
14 int main()
15 {
16     int n,k;
17     int cake = 0;
18     int part = 0;
19     int num = 0;
20     while (cin>>n>>k)
21     {
22         while (n--)
23         {
24            cin >> part;
25            cake += part;
26            if (cake >= k )
27            {
28                cake = 0 ;
29                num ++;
30            }
31         }
32         if (cake < k )
33         {
34             num ++;
35         }
36         cout << num <<endl;
37     }
38 
39 
40     return 0;
41 }

 

100分答案:

 1 #include <iostream>
 2 using namespace std;
 3 
 4 int main()
 5 {
 6     int n, k, ans = 0, s = 0, a;
 7     cin >> n >> k;
 8     while (n--)
 9     {
10         cin >> a;
11         s += a;
12         if (s >= k)
13         {
14             s = 0;
15             ans++;
16         }
17     }
18     if (s)ans++;
19     cout << ans;
20     return 0;
21 }

 

第一次做的只有20分,经过改进发现,if (cake)不要写成 if (cake < k ),因为如果是刚刚好,cake应该为0,大于0的话才是蛋糕不够的的情况。要注意边界问题
另外能不使用数组而使用一次性变量的情况就使用变量,这不浪费内存呢么?

中间数

* 
 1 #include <iostream>
 2 #include <algorithm>
 3 #include <string.h>
 4 #include <string>
 5 #include <stdio.h>
 6 #include <iomanip>
 7 using namespace std;
 8 /*
 9     题目:分蛋糕
10     思路:
11 */
12 
13 bool equals(int a[],int n,int mid)
14 {
15     int lit = 0;
16     int big = 0;
17         for (int i = 0 ;i < (n-1)/2 ; i++)
18     {
19         if (a[i] < mid)
20             lit++;
21     }
22     for (int i = (n-1)/2+1 ;i < n ; i++)
23     {
24         if (a[i] > mid)
25             big++;
26     }
27     if (lit == big)
28         return true;
29 }
30 
31 int main()
32 {
33     int n;
34     int a[1000];
35     bool flag = 1;
36     while ( cin  >>  n )
37     {
38         for (int i = 0;i<n;i++)
39             cin >> a[i];
40 
41         sort(a,a+n);
42         if ( n % 2 != 0 )
43     {
44         int mid = a[(n-1)/2];
45         if (equals(a,n,mid)){
46             cout << mid <<endl;
47             flag = 0;
48         }
49 
50     }
51     else
52     {
53         int mid1= a[(n-1)/2];
54         int mid2= a[(n+1)/2];
55         if (equals(a,n,mid1)){
56             cout <<mid1 <<endl;
57             flag = 0;
58         }
59          else
60             if (equals(a,n,mid2))
61             {
62                 cout <<mid2<<endl;
63                 flag = 0;
64             }
65     }
66     if (flag)
67         cout << -1 <<endl;
68 
69     }
70 
71     return 0;
72 }

 

分数 : 80
满分答案:减去与两侧相同的数

 1 #include <iostream>
 2 #include <algorithm>
 3 #include <string.h>
 4 #include <string>
 5 #include <stdio.h>
 6 #include <iomanip>
 7 using namespace std;
 8 /*
 9     题目:分蛋糕
10     思路:
11 */
12 
13 
14 const int N = 1000;
15 int a[N];
16 int main()
17 {
18     int n;
19     while ( cin  >>  n )
20     {
21         for (int i = 0;i<n;i++)
22             cin >> a[i];
23 
24         sort(a,a+n);
25         int mid = a[n/2];
26         int left = n/2;
27         int right = n - left - 1;
28         for (int i = 0 ;i < n/2 ; i++)
29             if (a[i] == mid )
30                 left -- ;
31         for (int i = n/2+1 ;i < n; i++)
32             if (a[i] == mid )
33                 right -- ;
34 
35         if (left == right)
36             cout << mid <<endl;
37         else
38             cout << -1<<endl;
39     }
40     return 0;
41 }

 

最大波动

 1    * 不用数组,三个变量解决问题
 2 #include <iostream>
 3 #include <algorithm>
 4 #include <string.h>
 5 #include <string>
 6 #include <stdio.h>
 7 #include <iomanip>
 8 using namespace std;
 9 /*
10     题目:
11     思路:
12 */
13 
14 const int N = 1000;
15 int a[N];
16 
17 int main()
18 {
19     int n;
20     int minN = 0;
21     while (cin >>n)
22     {
23         for (int i=0;i < n;i++)
24         {
25             cin >> a[i];
26         }
27         for (int i = 0 ;i<n-1;i++)
28         {
29             if (abs(a[i+1] - a[i])> minN )
30             {
31                 minN = abs(a[i+1]-a[i]);
32             }
33         }
34         cout << minN <<endl;
35     }
36     return 0;
37 }
38 * 不需要使用数组的方法, 先输入第一个数,后面的数循环输入
39 int main(void)  
40 {  
41     int n, first, second, delta, maxval=0;  
42 
43     // 输入n,输第1个数(从逻辑上来说应该写两句,为了简洁只需要写一句)  
44     scanf("%d%d", &n, &first);  
45 
46     while(--n) {  
47         // 输入第2至第n个数  
48         scanf("%d", &second);  
49 
50         // 求差值(波动值),取绝对值,求最大值  
51         delta = second - first;  
52         if(delta<0)  
53             delta = -delta;  
54         maxval = MAX(maxval, delta);  
55 
56         first = second;  
57     }  
58 
59     // 输出结果  
60     printf("%d
", maxval);  
61 
62     return 0;  
63 }  

 

折点计数

 1 *
 2 #include <iostream>
 3 #include <algorithm>
 4 #include <string.h>
 5 #include <string>
 6 #include <stdio.h>
 7 #include <iomanip>
 8 using namespace std;
 9 /*
10     题目:
11     思路:
12 */
13 
14 
15 int main()
16 {
17     // 求左边大右边大或左边小右边小的点的个数
18     int n;
19     int l, m ,r;
20     int num = 0;
21     while (cin >> n)
22     {
23         cin >>l>>m;
24         for (int i=0;i<n-2;i++)
25         {
26             cin >> r;
27             if ((l < m && r < m) || (l > m && r > m ))
28                 num ++;
29             l = m; m = r;
30         }
31         cout << num <<endl;
32 
33     }
34     return 0;
35 }

 

游戏

vector 没做出来,生气技术分享图片
1. 首先想到vector,注意vector的循环方法 迭代器+size()判断
2. 使用erase的时候应当避免使用迭代器
3. 如果不使用STL,需要做一个变量标记

  1 #include <iostream>
  2 #include <string.h>
  3 #include <stdio.h>
  4 #include <stdlib.h>
  5 #include <algorithm>
  6 #include <vector>
  7 #define maxSize 20
  8 #define ERROR -1
  9 using namespace std;
 10 /*
 11      CCF :2017-12-2
 12     Time : 游戏
 13     Date : 2018/3/14
 14 
 15 */
 16 struct stu
 17 {
 18     int num;
 19     int id;
 20 };
 21 int main()
 22 {
 23 
 24     int n,k;
 25     stu s;
 26     int i;
 27     vector<stu>::iterator iter;
 28     while (cin>>n>>k)
 29     {
 30         vector<stu> vec;
 31         for (int i = 0 ;i < n ; i++)
 32         {
 33             s.id = i+1;
 34             vec.push_back(s);
 35         }
 36 
 37 
 38         int i = 0;
 39         while (vec.size() > 1)
 40         {
 41             for (iter = vec.begin(); iter != vec.end();i++)
 42             {
 43                 iter->num = i+1;
 44                 cout << "num :"<<iter->num<< "  id :"<<iter->id<<endl;
 45 
 46                 if (iter->num%k == 0 || iter->num % 10 == k)
 47                 {
 48                     cout << iter->id <<"号小朋友报数" << iter->num << "被淘汰" <<endl;
 49                     iter = vec.erase(vec.begin()+ iter->id - 1);
 50                 }
 51                 else
 52                     iter ++;
 53 
 54             }
 55         }
 56         cout << vec[0].id;
 57 
 58     }
 59     return 0;
 60 }
 61 * 正确:
 62 #include <iostream>
 63 #include <string.h>
 64 #include <stdio.h>
 65 #include <stdlib.h>
 66 #include <algorithm>
 67 #include <vector>
 68 #define maxSize 20
 69 #define ERROR -1
 70 using namespace std;
 71 /*
 72      CCF :2017-12-2
 73     Time : 游戏
 74     Date : 2018/3/14
 75 
 76 */
 77 
 78 int main()
 79 {
 80     int n,k;
 81     cin >> n >> k;
 82     vector<int> vec;
 83     for (int i=0;i<n;i++)
 84         vec.push_back(i+1);
 85     int i = -1,no = 0;
 86     while (vec.size() > 1){
 87         no ++;
 88         i ++;
 89         i = i % vec.size(); // ★★★★ 相当于循环的作用
 90         if ( no % k == 0 || no % 10 == k)
 91         {
 92             vec.erase(vec.begin()+i);
 93             i--;
 94         }
 95 
 96     }
 97     cout << vec[0] <<endl;
 98 
 99     return 0;
100 }
101 * 从第一个进队的元素开始取,并pop()弹出队列,如果no符合要求则不行动否则push()到队列中。和学生的顺序无关?
102  while(!q.empty()) {  
103         head = q.front();  
104         q.pop();  
105 
106         no++;  
107         if(no % k == 0 || no % 10 == k)  
108             ;  
109         else  
110             q.push(head);  
111     }  
112 * 变量标记
113 const int N = 1000;  
114 bool flag[N];  
115 
116 int main()  
117 {  
118     int n, k;  
119 
120     // 读入数据  
121     cin >> n >> k;  
122 
123     // 初始化  
124     memset(flag, false, sizeof(flag));  
125 
126     // 模拟出局过程  
127     int i = -1, no = 0, cnt = n;  
128     while(cnt > 1) {  
129         i++;  
130         i %= n;  
131         if(!flag[i]) {  
132             no++;  
133             if(no % k == 0 || no % 10 == k) {  
134                 flag[i] = true;  
135 
136                 cnt--;  
137             }  
138         }  
139     }   
140     return 0;  
141 }  

 

ISBN

首先想到string,字符与整数的转化过程不要忘记!

 1 #include <iostream>
 2 #include <algorithm>
 3 #include <string.h>
 4 #include <string>
 5 #include <stdio.h>
 6 #include <iomanip>
 7 #include <vector>
 8 #include <queue>
 9 using namespace std;
10 /*
11     题目:ISBN号码
12     思路:
13 
14 */
15 
16 
17 int main()
18 {
19     string s;
20     cin >> s;
21     int c = 1;
22     int sum = 0;
23     for (int i = 0 ; i < s.length()-1 ;i ++)
24     {
25         if (s[i] != -){
26             sum += (s[i]-0)*c;
27             c++;
28         }
29     }
30     int c1 = sum % 11;
31     char cc;
32     // 逻辑上的错误!
33     // 如果cc = x,不应该被认为是不正确的一类
34     if (c1 == 10)
35         cc = X;
36     else
37         cc = 0+c1; // 统一转化为字符
38 
39     if ( cc == s[s.length()-1])
40         cout << "Right" << endl;
41     else
42     {
43         s[s.length()-1] = cc;
44         cout <<s<< endl;
45     }
46 
47 
48 
49     return 0;
50 }

 

窗口

窗口和点击操作用结构体实现,窗口从上到下的顺序用order数组表示,为了标记每个窗口的位置,给窗口结构体增加num序号,便于进行窗口移动的调整。

  1 #include <iostream>
  2 #include <algorithm>
  3 #include <string.h>
  4 #include <string>
  5 #include <stdio.h>
  6 #include <iomanip>
  7 #include <vector>
  8 #include <queue>
  9 using namespace std;
 10 /*
 11     题目:窗口
 12     思路:
 13 
 14 */
 15 struct win{
 16     int x1;
 17     int y1;
 18     int x2;
 19     int y2;
 20     int no;
 21 }win[11];
 22 
 23 struct point
 24 {
 25     int x;
 26     int y;
 27 }point[11];
 28 int order[11];
 29 
 30 
 31 int belongToWin(int j,int x,int y)
 32 {
 33     if ( (x >= win[j].x1 && x <= win[j].x2) &&(y >= win[j].y1 && y <= win[j].y2))
 34         return 1;
 35     else
 36         return 0;
 37 }
 38 void moveTo(int j,int n)
 39 {
 40     // order中移动顺序
 41     int  t = order[j];
 42     for (int i = j ; i < n-1 ; i++ )
 43     {
 44         order[i] = order[i+1];
 45     }
 46     order[n-1] = t;
 47 }
 48 int main()
 49 {
 50     int N,M;
 51     cin >> N >> M;
 52     int i;
 53     for (i = 0 ; i < N ;i++)
 54     {
 55         cin >> win[i].x1 >> win[i].y1 >> win[i].x2 >> win[i].y2;
 56         win[i].no = i+1;
 57         order[i] = i+1;
 58     }
 59     for ( i = 0 ; i < M ; i++)
 60     {
 61         cin >> point[i].x >> point[i].y ;
 62     }
 63     // 对point操作进行循环,每次找出位于最上层(order中大的)的窗口:改变order移动到最外层,输出窗口序号
 64     for ( i = 0 ;i < M ; i++)
 65     {
 66         bool flag = 1;
 67 
 68         for (int j = N-1 ; j >= 0 ; j--) // 从order的上层开始往下找符合点击范围内的
 69         {
 70             if (belongToWin(j,point[i].x,point[i].y))
 71             {
 72                 if (j != N-1)
 73                 {
 74                     // 不是最外层
 75                     moveTo(j,N); // 移动到最外层的函数
 76                 }
 77                 cout << win[order[N-1]-1].no <<endl;
 78                 flag = 0;
 79                 break;
 80             }
 81         }
 82         if (flag) // 都没点击到窗口内
 83             cout <<"IGNORED"<<endl;
 84 
 85     }
 86 
 87 
 88 
 89     return 0;
 90 }
 91 * 40 
 92 // 判断哪个窗口被点击  
 93         for(int j=0; j<n; j++) {  
 94             if(win[order[j]].x1 <= point[i].x && point[i].x <= win[order[j]].x2 &&  
 95                     win[order[j]].y1 <= point[i].y && point[i].y <= win[order[j]].y2) {  
 96                 // 得到窗口号  
 97                 winno = win[order[j]].winno;  
 98 
 99                 // 将被点击的窗口移到最前端  
100                 temp = order[j];  
101                 for(int k=j; k>0; k--)  
102                     order[k] = order[k-1];  
103                 order[0] = temp;  
104 
105                 break;  
106             }  
107         }  
108 
109         // 输出结果  
110         if(winno == -1)  
111             cout << "IGNORED" << endl;  
112         else  
113             cout << winno << endl;  
114     }  

 

画图

矩阵用结构体表示,整个画布用数组表示

 1 #include <iostream>
 2 #include <algorithm>
 3 #include <string.h>
 4 #include <string>
 5 #include <stdio.h>
 6 #include <iomanip>
 7 #include <vector>
 8 #include <queue>
 9 using namespace std;
10 /*
11     题目:
12     思路:
13 
14 */
15 const int N = 101;
16 struct rec
17 {
18     int x1,y1,x2,y2;
19 }rec[N];
20 
21 int paper[N][N] ;
22 // memset(paper,1,sizeof(paper))
23 
24 int main()
25 {
26     int n;
27     int i,j,k;
28     cin >> n ;
29     for ( i = 0 ;i < n ; i++)
30     {
31         cin >> rec[i].x1 >> rec[i].y1 >> rec[i].x2>>rec[i].y2;
32     }
33     for (i = 0 ; i < N ; i++)
34         for (j = 0 ; j < N ;j ++)
35             paper[i][j] = 0;
36 
37     for (i = 0 ;i < n ;i++)
38     {
39         for ( j = rec[i].x1 ; j < rec[i].x2 ; j++)
40             for ( k = rec[i].y1 ; k < rec[i].y2 ; k++)
41         {
42             paper[j][k] = 1;
43         }
44     }
45 
46     int num = 0;
47      for (i = 0 ; i < N ; i++)
48         for (int j = 0 ; j < N ;j ++)
49             if (paper[i][j])
50                 num ++;
51 
52     cout << num <<endl;
53 
54 
55 
56 
57     return 0;
58 }

 

数字排序

每个数字对应一个数量,使用map表示,一次循环输入,map自动排序
排序的工具使用优先队列,但需要创建对应Node结点和cmp函数,自定义优先队列的使用规则
优先队列特殊:大堆输出,所以和正常的cmp函数要反着写

 1 #include <iostream>
 2 #include <algorithm>
 3 #include <string.h>
 4 #include <string>
 5 #include <stdio.h>
 6 #include <iomanip>
 7 #include <vector>
 8 #include <queue>
 9 #include <map>
10 using namespace std;
11 /*
12     题目:
13     思路:
14     1.出现次数递减
15     2. 出现次数相同时,先输出值小的
16 
17     1. 使用map进行统计
18     2. 使用优先队列进行排序
19 
20 */
21 struct Node
22 {
23     int val,c ;
24 };
25 
26 struct cmp{
27     bool operator()(Node a, Node b){
28         if(a.c == b.c)  return a.val>b.val;
29         return a.c < b.c;
30     }
31 };
32 int main()
33 {
34     int n;
35     cin >> n;
36     map<int,int> m ;
37     int t;
38     // 1.输入数据统计出现次数
39     for (int i = 0; i < n ; i++){
40         cin >> t;
41         m[t] += 1;
42     }
43     /*debug*/
44     // 2. 利用优先队列进行排序
45     // priority_queue<map<int,int>,vector<map<int,int>,cmp> q; 不能把map作为队列元素
46     // 把map集合中的值一对一对取出,存入node中,插入队列
47     priority_queue<Node,vector<Node>,cmp> q;
48     Node no ;
49     map<int,int>::iterator iter ;
50     for (iter = m.begin() ; iter !=m.end() ; iter++)
51     {
52         no.val = iter->first ;
53         no.c = iter->second ;
54         q.push(no);
55     }
56 
57 
58 
59     // print
60     while(!q.empty()){
61         cout<<q.top().val<< <<q.top().c<<endl;
62         q.pop();
63     }
64 
65 
66 
67     return 0;
68 }

 

公共钥匙盒

  1. 钥匙盒用数组表示,存储钥匙ID,没有则为-1
  2. 老师的时间、操作不同,对钥匙盒的改变也不同,需要创建坐标轴的元素改变结点Node并初始化,为了排序,使用优先队列存储Node结点,按照自定义排序规则排序。遍历优先队列。
  1 #include <iostream>
  2 #include <string.h>
  3 #include <stdio.h>
  4 #include <stdlib.h>
  5 #include <algorithm>
  6 #include <vector>
  7 #include <queue>
  8 #include <stack>
  9 #define maxSize 20
 10 #define ERROR -1
 11 using namespace std;
 12 /*
 13      CCF :2017-12-2
 14     Time : 公共钥匙盒(模拟题)
 15     思路 :
 16     1. 如果在时间坐标轴上标记,某个事件,还/拿,某把钥匙,定义为一个操作节点
 17     2. 使用优先队列对操作节点进行排序,时间优先,时间相同先还再取,操作相同钥匙号小的有限
 18     3. 遍历优先队列中的操作,定义钥匙盒数组,没有钥匙为-1,利用循环从小到大找空位
 19 
 20 */
 21 const int K = 1001;
 22 struct Node
 23 {
 24     int key; // 钥匙ID
 25     int time; // 时间
 26     char op;// 还钥匙R,取钥匙G
 27     bool operator < (Node a) const
 28     {
 29         if (time != a.time)
 30         {
 31             return time > a.time ;
 32         }else if (op != a.op){
 33             return op < a.op;
 34         }
 35         else{
 36             return key > a.key ;
 37         }
 38     }
 39 
 40 };
 41 
 42 const int N1 = 10000;
 43 int box[N1]; // 钥匙盒子
 44 
 45 int main()
 46 {
 47     int n,k,c; // n 个房间,k 个老师
 48     // 输入老师的信息
 49     cin >> n >> k ;
 50 
 51     // 初始化钥匙盒信息
 52     memset(box,0,N1);
 53     for (int i = 0 ; i < n ; i++)
 54         box[i] = i+1;
 55 
 56     // 初始化优先队列,放入取钥匙和拿钥匙操作节点
 57     Node a;
 58     int last;
 59     priority_queue<Node> p;
 60     for (int i = 0 ; i < k ; i++ )
 61     {
 62         cin >> a.key >> a.time >> last;
 63         a.op = G;
 64         p.push(a);
 65         a.time = last + a.time;
 66         a.op = R;
 67         p.push(a);
 68 
 69    }
 70    /*debug
 71    while (!p.empty())
 72    {
 73        a = p.top();
 74        cout << a.key << " ";
 75        p.pop();
 76    }
 77    */
 78 
 79 
 80     // 遍历优先队列
 81     while (!p.empty())
 82     {
 83         a = p.top();
 84         p.pop();
 85         if (a.op == G)
 86         {
 87             for (int i = 0; i<n;i++)
 88             {
 89                 if (box[i] == a.key)
 90                 {
 91                     box[i] = -1;
 92                     break;
 93                 }
 94             }
 95         }
 96         if (a.op == R)
 97         {
 98             for (int i=0;i<n;i++)
 99             {
100                 if (box[i] == -1)
101                 {
102                     box[i] = a.key;
103                     break;
104                 }
105             }
106         }
107     }
108 
109     // print
110     for (int i = 0 ; i< n-1;i++)
111     {
112         cout << box[i] << " ";
113     }
114     cout <<box[n-1]<<endl;
115 
116 
117 
118 
119 
120 
121     return 0;
122 }

 

学生排队

vector 出队erase,入队insert,注意的是这两者的具体函数规则

 1 #include <iostream>
 2 #include <string.h>
 3 #include <stdio.h>
 4 #include <stdlib.h>
 5 #include <algorithm>
 6 #include <vector>
 7 #include <queue>
 8 #include <stack>
 9 #define maxSize 20
10 #define ERROR -1
11 using namespace std;
12 /*
13      CCF :
14     Time :
15     思路 :
16 
17 */
18 void print(vector<int> vec)
19 {
20         for (int i= 0;i<vec.size();i++)
21     {
22         cout <<vec[i]<<" ";
23     }
24 }
25 
26 int main()
27 {
28     int n;
29     cin >>n;
30     int m;
31     cin >> m;
32     int p,q;
33 
34     // 构造队列
35     vector<int> vec;
36     for (int i=0;i<n;i++)
37     {
38         vec.push_back(i+1);
39     }
40 
41     vector<int>::iterator iter;
42     for (int i= 0;i<m;i++)
43     {
44         cin >>p >>q;
45         // 对队列进行操作
46         for (iter =vec.begin() ; iter !=vec.end();iter++)
47         {
48             if (*iter == p)
49                 break;
50         }
51         if (++iter != vec.end())
52         {
53             vec.erase(--iter);
54 //print(vec);
55             vec.insert(iter+q,p);
56      //       print(vec);
57         }
58         else
59         {
60             vec.pop_back();
61        //     print(vec);
62             iter = vec.end();
63             vec.insert(iter+q,p);
64          //   print(vec);
65         }
66     }
67 
68     // print
69     for (int i= 0;i<vec.size();i++)
70     {
71         cout <<vec[i]<<" ";
72     }
73 
74     return 0;
75 }

 

工资计算

分段问题:正着好求,反着则先正着创建一个表格,然后通过表格找到大致范围,然后推回去。

 1 #include <iostream>
 2 #include <string.h>
 3 #include <stdio.h>
 4 #include <stdlib.h>
 5 #include <algorithm>
 6 #include <vector>
 7 #include <queue>
 8 #include <stack>
 9 #define maxSize 20
10 #define ERROR -1
11 using namespace std;
12 /*
13      CCF :
14     Time :
15     思路 :
16 
17 */
18 int gal[10]={0,1500,4500,9000,35000,55000,80000};
19 float tax[10] ={0,0.03,0.1,0.2,0.25,0.3,0.35,0.45};
20 int sal[11]={0,3500,4955,7654,11253};
21 int main()
22 {
23     float t;
24     cin >>t;
25     float a = t - 3500; // 收税工资部分
26 
27     float sum = 3500;
28     for (int i=1;i<7 ;i++)
29     {
30         sum += (gal[i]-gal[i-1])*(1-tax[i]);
31         sal[i+1] = sum;
32     }
33   //  for (int i = 0;i<8;i++)
34  //  cout << sal[i]<<endl;
35     float sum2 = 3500;
36     for (int i = 1;i<8;i++)
37     {
38         if (t<sal[i] && t>sal[i-1])
39         {
40             a = (t-sal[i-1])/(1-tax[i-1]);
41             sum2 += a;
42             sum2+=gal[i-2];
43         }
44         if ( t > sal[7])
45         {
46             a = (t-sal[7])/(1-tax[7]);
47             sum2 +=gal[6];
48         }
49     }
50     cout << (int)sum2 << endl;
51 
52 
53 
54 
55 
56 
57 
58 
59     return 0;
60 }

 

60

 1 /* CCF201612-2 工资计算 */  
 2 
 3 #include <iostream>  
 4 
 5 using namespace std;  
 6 
 7 //#define DEBUG  
 8 
 9 int salaryrange[] = {3500, 3500+1500, 3500+4500, 3500+9000, 3500+35000, 3500+55000, 3500+80000 };   
10 // 税前工资的范围
11 int taxrate[] = {3, 10, 20, 25, 30, 35, 45};  
12 const int SIZE = sizeof(salaryrange) / sizeof(int); 
13 // 定义长度不定的数组时计算size的方法 
14 
15 int range[SIZE];  
16 
17 int main()  
18 {  
19     int t, s;  
20 
21     // 计算税后工资范围   
22     range[0] = salaryrange[0];  
23     for(int i=1; i<SIZE; i++) {  
24         range[i] = range[i-1] + (salaryrange[i] - salaryrange[i-1])  
25                 - (salaryrange[i] - salaryrange[i-1]) * taxrate[i-1] / 100;  
26     }  
27 
28 #ifdef DEBUG  
29     for(int i=0; i<SIZE; i++)  
30         cout << range[i] << " ";  
31     cout << endl;  
32 #endif  
33 
34     // 输入数据:  
35     cin >> t;  
36 
37     // 计算收入范围  
38     int i;  
39     for(i=0; i<SIZE; i++)  
40         if(t <= range[i])  
41             break;  
42 
43     // 计算税前工资  
44     if(i == 0)  
45         s = t;  
46     else {  
47         s = salaryrange[i-1] + (t - range[i-1]) * 100 / (100 - taxrate[i-1]);  
48     }  
49 
50     // 输出结果  
51     cout << s << endl;  
52 
53     return 0;  
54 }  

 

消除游戏

对于数组的灵活使用,两个数组,一个是变量标记数组

 1 * CCF201512-2 消除游戏 */  
 2 
 3 #include <stdio.h>  
 4 #include <string.h>  
 5 
 6 #define N 30  
 7 
 8 int a[N][N], t[N][N];  
 9 
10 int main(void)  
11 {  
12     int n, m, i, j;  
13 
14     scanf("%d%d", &n, &m);  
15     for(i=0; i<n; i++)  
16         for(j=0; j<m; j++)  
17             scanf("%d", &a[i][j]);  
18 
19  // 对二维数组的灵活运用
20     memset(t, 0, sizeof(t));  
21     // 进行行标记(可以消除则置1)  
22     for(i=0; i<n; i++)  
23         for(j=0; j<m-2; j++)  
24             if(a[i][j]== a[i][j + 1] && a[i][j + 1] == a[i][j +2])  
25                 t[i][j] = t[i][j + 1] = t[i][j + 2] = 1;  
26     // 进行列标记(可以消除则置1)  
27     for(j=0; j<m; j++)  
28         for(i=0; i<n-2; i++)  
29             if(a[i][j] == a[i + 1][j] && a[i + 1][j] == a[i + 2][j])  
30                 t[i][j] = t[i + 1][j] = t[i + 2][j] = 1;  
31 
32     // 重置矩阵a  
33     for(i=0; i<n; i++)  
34         for(j=0; j<m; j++)  
35             if(t[i][j])  
36                 a[i][j] = 0;  
37 
38     // 输出结果  
39     for(i=0; i<n; i++) {  
40         for(j=0; j<m; j++) {  
41             if(j != 0)  
42                 printf(" ");  
43             printf("%d", a[i][j]);  
44         }  
45         printf("
");  
46     }  
47 
48     return 0;  
49 }  

 

火车购票

 1 #include <iostream>
 2 #include <map> 
 3 /* run this program using the console pauser or add your own getch, system("pause") or input loop */
 4 // 火车购票问题
 5  using namespace std;
 6  const int LINE = 20;
 7  const int NUM = 5;
 8 int main(int argc, char** argv) {
 9     int n,v,start,end,j;
10     cin >> n ;
11     // 一行的座位打包,记录行数以及这行的剩余位置数 
12     map<int ,int> m;
13     // m初始化
14     map<int,int>::iterator iter;
15     for (int i = 1 ;i <= LINE ; i++ )
16     {
17         m[i] = NUM ;  
18      } 
19     for (int i = 0 ; i < n ; i++)
20     {
21         cin >> v; 
22         // 1. 一行内满足购票
23         // 逻辑:优先从小选择一行内的票,一行内从小到大排列 
24         for (iter = m.begin() ; iter != m.end() ; iter ++)
25         {
26             if ( iter->second >= v )
27             {
28                 // 分配座位,输出
29                 start = (iter->first - 1) * NUM + NUM - iter->second + 1;
30                 end = start + v - 1 ; 
31                 for (j = start ; j < end;j++)
32                 {
33                     cout << j <<" ";
34                 }
35                 cout << end << endl;
36                 // 是否要删除座位 
37                 if (iter->second == v )
38                 {
39                     m.erase(iter);
40                 }else
41                 {
42                     iter->second = iter->second - v;
43                 }
44                 v = 0 ;
45                 break; 
46             }
47         }
48         // 2.多行购票  需要判断是不是最后一个 
49         bool isend = false; 
50         while (v > 0)
51         {
52             for (iter = m.begin() ; iter!=m.end();iter ++){
53                 if (iter->second >= v ) 
54             {
55                     // 分配座位,输出
56                 start = (iter->first - 1) * NUM + NUM - iter->second + 1;
57                 end = start + v - 1 ; 
58                 for (j = start ; j < end;j++)
59                 {
60                     cout << j <<" ";
61                 }
62                 if (!isend) 
63                     cout << end << " ";
64                 else
65                 {
66                     cout << end << endl;
67                     isend = true;
68                 }
69                 // 是否要删除座位 
70                 if (iter->second == v )
71                 {
72                     m.erase(iter);
73                 }else
74                 {
75                     iter->second = iter->second - v;
76                 }
77 
78             }else 
79             {
80                 start = (iter->first - 1) * NUM + NUM - iter->second + 1;
81                 end = start + iter->second - 1 ; 
82                 for (int j = start ; j <= end;j++)
83                 {
84                     // 一定没有结束 
85                     cout << j <<" ";
86                 }   
87                 v = v - iter->second; 
88                 // 要删除座位 
89                 m.erase(iter);  
90             }   
91             } 
92 
93         }
94 
95      } 
96     return 0;
97 }

 

俄罗斯方块

coard 记录方格的具体位置,这样不用就4*4遍历了

 1 #include <iostream>
 2 #include <map> 
 3 /* run this program using the console pauser or add your own getch, system("pause") or input loop */
 4 
 5  using namespace std;
 6 
 7 const int ROW = 15;  
 8 const int COL = 10;  
 9 const int N = 4;  
10 
11 int board[ROW+1][COL];  
12 int block[N][N];  
13 struct {  
14     int row, col;  
15 } coords[N];
16 
17 int main(int argc, char** argv) {
18 
19      int row, col;  
20 
21     // 输入数据  
22     for(int i=0; i<ROW; i++)  
23         for(int j=0; j<COL; j++)  
24             cin >> board[i][j];  
25     for(int i=0; i<N; i++)  
26         for(int j=0; j<N; j++)  
27             cin >> block[i][j];  
28     cin >> col;  
29 
30     // 底边全放1  
31     for(int j=0; j<COL; j++)  
32         board[ROW][j] = 1;  
33 
34     // 提取小方块坐标  
35     int k = 0;  
36     for(int i=N-1; i>=0; i--)  
37         for(int j=0; j<N; j++)  
38             if(block[i][j] == 1) {  
39                 coords[k].row = i;  
40                 coords[k].col = j;  
41                 k++;  
42             }  
43     // 模拟小方块落下过程  
44     row = 1;  
45     col--;  // 第i列表示的是数组中的i-1 
46     bool checkflag;  
47     for(;;) {  
48         checkflag = false;  
49 
50         for(int i=0; i<N; i++)  
51             if(board[row + coords[i].row][col + coords[i].col] == 1) {  
52                 checkflag = true;  
53                 break;  
54             }  
55 
56         if(checkflag)  
57             break;  
58 
59         row++;  
60     }  
61     row--;  // 如果再往下一行会接触到1,就需要上移一行;或者是到了最底层 
62 
63     // 合并小方块到方格  
64     for(int i=0; i<N; i++)  
65         board[row + coords[i].row][col + coords[i].col] = 1;  
66 
67        // 输出结果  
68     for(int i=0; i<ROW; i++) {  
69         for(int j=0; j<COL; j++) {  
70             if(j != 0)  
71                 cout << " ";  
72             cout << board[i][j];  
73         }  
74         cout << endl;  
75     }  
76     return 0;
77 }

 

以上是关于CCF 第二题的主要内容,如果未能解决你的问题,请参考以下文章

算法题CCF CSP第二题练习(更新中)

CCF CSP历年一二题代码汇总

记第十七次CCF CSP认证

20160317第二题

下面的第二题怎么做啊,求解题思路,特别是白色紫色红色粉色的基因型怎么找啊?

820 2019读程序的第二题 ,字符串