本文记录CCF-CSP算法题解。
注:#include<bits/stdc++.h>包含所有的C++头文件。
2018年
12月
201812-1 小明上学
1 | r, y, g = map(int, input().split()) |
2 | n = int(input()) |
3 | t = 0 |
4 | # 出发 |
5 | for i in range(n): |
6 | path = list(map(int, input().split())) |
7 | if path[0]==0 or path[0] == 1: # 经过道路/等红灯 |
8 | t += path[1] |
9 | elif path[0] == 2: # 等黄灯(之后还要等红灯) |
10 | t += path[1] + r |
11 | print(t) |
201812-2 小明放学
1 | r, y, g = map(int, input().split()) |
2 | n = int(input()) |
3 | total_time = 0 |
4 | # 出发 |
5 | for i in range(n): |
6 | m_type, m_time = map(int, input().split()) |
7 | if m_type == 0: # 经过道路 |
8 | total_time += m_time |
9 | continue |
10 | # 转成距绿灯结束的时间 |
11 | if m_type == 1: # 红灯 |
12 | m_time += g |
13 | m_type = 3 |
14 | if m_type == 2: # 黄灯(之后还要等红灯) |
15 | m_time += (r + g) |
16 | m_type = 3 |
17 | if m_type == 3: # 绿灯 |
18 | pass |
19 | now_time = (m_time - total_time) % (g+r+y) # 当前循环距绿灯结束的时间 |
20 | if now_time > g: # 经过该路口时不为绿灯 |
21 | total_time += (now_time - g) # 加上要等待的时间 |
22 | print(total_time) |
201812-3 CIDR合并
201812-4 数据中心
201812-5 管道清洁
9月
201809-1 卖菜
1 | n = int(input()) |
2 | p = list(map(int, input().split())) # 0~n-1 |
3 | o = [0]*n |
4 | o[0] = int((p[0]+p[1])/2) |
5 | o[-1] = int((p[-2]+p[-1])/2) |
6 | for i in range(1, n-1): |
7 | o[i] = int((p[i-1]+p[i]+p[i+1])/3) |
8 | for i in o: |
9 | print(i, end=' ') |
201809-2 买菜
1 | n = int(input()) |
2 | H = [] # 小H装车时间段 |
3 | W = [] # 小W装车时间段 |
4 | for i in range(n): |
5 | H.append(tuple(map(int, input().split()))) |
6 | for i in range(n): |
7 | W.append(tuple(map(int, input().split()))) |
8 | tlate = max(H[-1][-1], W[-1][-1]) # 最晚时间点 |
9 | timecnt = [0]*tlate # 时间点计数 |
10 | for s, e in H: |
11 | for i in range(s, e): |
12 | timecnt[i] += 1 |
13 | for s, e in W: |
14 | for i in range(s, e): |
15 | timecnt[i] += 1 |
16 | print(timecnt.count(2)) |
201809-3 元素选择器
1 | n, m = map(int, input().split()) # 文档行数、待查询选择器个数 |
2 | doc = [] |
3 | sel = [] |
4 | # 结构化文档内容 |
5 | for i in range(n): |
6 | doc.append(input()) |
7 | # 待查询的选择器 |
8 | for i in range(m): |
9 | sel.append(input()) |
10 | # 解析文档 |
11 | cons = [] |
12 | for i in range(n): |
13 | level = doc[i].count('.')//2 |
14 | tag = "" |
15 | tid = "" |
16 | if len(doc[i].split())==1: |
17 | tag = doc[i][level*2:] |
18 | else: |
19 | left, right = doc[i].split() |
20 | tag = left[level*2:] # 标签大小写不敏感 |
21 | tid = right # id大小写敏感 |
22 | pline = -1 |
23 | for j in range(i-1, 0-1, -1): |
24 | if cons[j]["level"] == level-1: |
25 | pline = j + 1 |
26 | break |
27 | cons.append({"tag":tag, "id":tid, "level":level, "pline":pline}) # 存信息为字典添加到列表 |
28 | # 元素选择器选择 |
29 | collection = [] # 结果保存列表 |
30 | for i in range(m): |
31 | collection.append([]) |
32 | if len(sel[i].split())==1: # 选择器不含空格 |
33 | if sel[i][0]!='#': # 标签选择器 |
34 | for j in range(n): |
35 | if cons[j]["tag"].lower() == sel[i].lower(): # 标签大小写不敏感 |
36 | collection[i].append(j+1) |
37 | else: # id选择器 |
38 | for j in range(n): |
39 | if cons[j]["id"] == sel[i]: # id大小写敏感 |
40 | collection[i].append(j+1) |
41 | else: # 后代选择器 |
42 | p = sel[i].split() |
43 | for j in range(n): |
44 | parent = j + 1 |
45 | k = len(p) - 1 |
46 | while k >= 0: # 从后向前迭代检查是否匹配 |
47 | match = False |
48 | if p[k][0]!='#': |
49 | if cons[parent-1]["tag"].lower() == p[k].lower(): |
50 | match = True |
51 | elif parent == j+1 and k==len(p)-1: # 第一次必须匹配上不然直接退出 |
52 | break |
53 | else: |
54 | if cons[parent-1]["id"] == p[k]: |
55 | match = True |
56 | elif parent==j+1 and k==len(p)-1: |
57 | break |
58 | if match: |
59 | k -= 1 |
60 | if k < 0: # 匹配成功 |
61 | collection[i].append(j+1) |
62 | break |
63 | if cons[parent-1]["pline"]==-1: # 没有父节点了仍未匹配成功即匹配失败 |
64 | break # 匹配失败退出 |
65 | parent = cons[parent-1]["pline"] # 取父节点继续检查匹配 |
66 | # 输出 |
67 | for x in collection: |
68 | print(len(x), " ".join(map(str, x))) |
201809-4 再卖菜
201809-5 线性递推式
3月
201803-1 跳一跳
1 | //CCF 201803-1 跳一跳 |
2 |
|
3 | using namespace std; |
4 | int jump(int &score, int &temp){ |
5 | int a; |
6 | cin >> a; |
7 | if(a == 1){ |
8 | score += 1; |
9 | temp = 0; |
10 | jump(score, temp); |
11 | } |
12 | else if(a == 2){ |
13 | temp += 2; |
14 | score += temp; |
15 | jump(score, temp); |
16 | } |
17 | return score; |
18 | } |
19 | int main(){ |
20 | int score = 0, temp = 0; |
21 | score = jump(score, temp); |
22 | cout << score << endl; |
23 | return 0; |
24 | } |
201803-2 碰撞的小球
1 | //CCF 201803-2 碰撞的小球 |
2 |
|
3 | using namespace std; |
4 | int main(){ |
5 | int n, L, t, i, j, k; //小球个数、线段长度、计算时刻等 |
6 | cin >> n >> L >> t; |
7 | int A[100]; //n个小球的初始位置(都为偶数) |
8 | int dirA[100]; //存放n个小球当前的运动方向:1为右、-1为左 |
9 | for(int i=0; i<n; i++){ |
10 | cin >> A[i]; |
11 | dirA[i] = 1; //所有小球方向初始化为右 |
12 | } |
13 | for(int i=1; i<=t; i++){ //t秒的循环 |
14 | for(j=0; j<n; j++){ |
15 | if((A[j]==L && dirA[j]==1) || (A[j]==0 && dirA[j]==-1)) //位于两个端点 |
16 | dirA[j] *= -1; //掉头 |
17 | else |
18 | for(k=0; k<n; k++) |
19 | if(A[j]==A[k] && j!=k) {//小球发生碰撞 |
20 | dirA[j] *= -1; |
21 | dirA[k] *= -1; |
22 | } |
23 | A[j] += dirA[j]; //更新当前位置 |
24 | } |
25 | } |
26 | for(int i=0; i<n; i++) |
27 | cout << A[i] << " "; |
28 | cout << endl; |
29 | return 0; |
30 | } |
201803-3 URL映射
1 | //CCF 201803-3 URL映射 |
2 |
|
3 | using namespace std; |
4 | struct reg{ |
5 | string name; |
6 | vector<string> regV; |
7 | reg(string n, vector<string> v):name(n), regV(v){} |
8 | }; //规则结构体 |
9 | vector<reg> regS; //规则向量 |
10 | vector<string> str2regV(string str){ //字符串转化为规则向量 |
11 | vector<string> res; |
12 | str = str.substr(1, str.size()-1); //substr: 从字符串指定位置复制指定数量的字符 |
13 | res.push_back("/"); |
14 | size_t pos = str.find("/"); |
15 | while(pos != string::npos){ //npos: npos表示string的结束位子 |
16 | res.push_back(str.substr(0, pos)); |
17 | res.push_back("/"); |
18 | str = str.substr(pos+1); //没有指定长度,从pos+1复制到字符串结尾 |
19 | pos = str.find("/"); |
20 | } |
21 | if(str.size()) res.push_back(str); |
22 | return res; |
23 | } |
24 | void urlMap(string str){ //完成URL映射 |
25 | vector<string> v = str2regV(str); //目标URL的规则向量 |
26 | for( size_t i=0; i<regS.size(); i++){ |
27 | vector<string> &r = regS[i].regV; //所有规则向量的每一项规则 |
28 | string res = regS[i].name; ////所有规则向量的每一项规则名称 |
29 | size_t lr = r.size(), lv = v.size(), j = 0, k = 0; |
30 | while(j<lr && k<lv){ |
31 | if(r[j] == v[k]){ j++, k++; continue; } |
32 | if(r[j] == "<path>"){ //路径 <path> |
33 | if(v[lv-1] == "/") break; |
34 | res += " "; |
35 | while(k < lv) res += v[k++]; |
36 | cout << res << endl; |
37 | return; |
38 | }else if(r[j] == "<int>"){ //整数 <int> |
39 | string num; |
40 | bool tag = 1; |
41 | for(size_t l=0; l<v[k].size(); l++){ |
42 | if(isdigit(v[k][l])) num+= v[k][l]; |
43 | else{ tag = 0; break; } |
44 | } |
45 | if(tag == 0) break; |
46 | size_t uz = 0; |
47 | while(num[uz]=='0' && uz<num.size()-1) ++uz; //去除前导0 |
48 | res += " " + num.substr(uz, num.size()-uz); |
49 | }else if(r[j] == "<str>"){ //字符串 <str> |
50 | res += " " + v[k]; |
51 | }else break; |
52 | j++; k++; |
53 | } |
54 | if(j==lr && k==lv){ |
55 | cout << res << endl; |
56 | return; |
57 | } |
58 | } |
59 | cout << "404" << endl; //匹配失败 |
60 | } |
61 | int main(){ |
62 | int n, m; //规则数、URL数 |
63 | cin >> n >> m; |
64 | for(int i=0; i<n; i++){ |
65 | string regStr, name; //规则字符串及其名称 |
66 | cin >> regStr >> name; |
67 | regS.push_back(reg(name, str2regV(regStr))); //构建规则向量 |
68 | } |
69 | while(m--){ //对每一个url依次映射 |
70 | string str; |
71 | cin >> str; |
72 | urlMap(str); |
73 | } |
74 | return 0; |
75 | } |
201803-4 棋局评估
1 | //CCF 201803-4 棋局评估 |
2 |
|
3 | using namespace std; |
4 | int A[3][3]; //棋盘 空白为0 |
5 | bool isrowsame(int i, int val) { //横向第i行都相同 |
6 | return A[i][0]==val && A[i][1]==val && A[i][2]==val; |
7 | } |
8 | bool iscolsame(int j, int val) { //竖向第j列都相同 |
9 | return A[0][j]==val && A[1][j]==val && A[2][j]==val; |
10 | } |
11 | bool isdiagsame(int val) { //斜方向的三个位置都相同 |
12 | return (A[0][0]==val && A[1][1]==val && A[2][2]==val) || (A[0][2]==val && A[1][1]==val && A[2][0]==val); |
13 | } |
14 | int countempty() { //计算空白格子个数 |
15 | int res = 0; |
16 | for(int i=0; i<3; i++) |
17 | for(int j=0; j<3; j++) |
18 | if(A[i][j] == 0) res++; |
19 | return res; |
20 | } |
21 | int iswin(int player) { //player: 1代表Alice, 2代表Bob |
22 | bool r = isrowsame(0, player) || isrowsame(1, player) || isrowsame(2, player); |
23 | bool c = iscolsame(0, player) || iscolsame(1, player) || iscolsame(2, player); |
24 | bool d = isdiagsame(player); |
25 | int w = r || c || d; //判断当前状态玩家是否胜出 |
26 | if(w == 0) return 0; //未胜出,继续游戏 |
27 | w = countempty() + 1; //该玩家胜出,计算分数,游戏结束 |
28 | return player==1 ? w : -w; |
29 | } |
30 | int dfs(int player){ |
31 | if(countempty() == 0) return 0; //棋盘已满,平局 |
32 | int Min = 10, Max = -10; |
33 | for(int i=0; i<3; i++) |
34 | for(int j=0; j<3; j++) { |
35 | if(A[i][j] == 0) { |
36 | A[i][j] = player; |
37 | int w = iswin(player); |
38 | if(w) { //棋局结束 |
39 | A[i][j] = 0; |
40 | return w>0 ? max(Max, w) : min(Min, w); |
41 | } |
42 | if(player == 1) Max = max(Max, dfs(2)); |
43 | else Min = min(Min, dfs(1)); |
44 | A[i][j] = 0; |
45 | } |
46 | } |
47 | return player==1 ? Max : Min; |
48 | } |
49 | int main() { |
50 | int T; //输入数据的组数 |
51 | cin >> T; |
52 | while(T--){ //依次处理每组数据并输出当前局面的得分 |
53 | for(int i=0; i<3; i++) |
54 | for(int j=0; j<3; j++) |
55 | cin >> A[i][j]; |
56 | int x = iswin(1), y = iswin(2); |
57 | if(x) cout << x << endl; |
58 | else if(y) cout << y << endl; |
59 | else cout << dfs(1) << endl; |
60 | } |
61 | return 0; |
62 | } |
学习参考:
201803-5 二次求和
2017年
12月
201712-1 最小差值
1 | //CCF 201712-1 最小差值 |
2 |
|
3 | using namespace std; |
4 | int main(){ |
5 | int n, num[1024], minval=10000; |
6 | cin >> n; |
7 | for(int i=0; i<n; ++i) |
8 | cin >> num[i]; |
9 | sort(num, num+n); |
10 | for(int i=1; i<n; ++i) |
11 | minval = min(minval,num[i]-num[i-1]); |
12 | cout << minval <<endl; |
13 | return 0; |
14 | } |
201712-2 游戏
1 | //CCF 201712-2 游戏 |
2 |
|
3 | using namespace std; |
4 | int main(){ |
5 | int n, k; |
6 | cin >> n >> k; |
7 | vector<int> win; //剩余人序列 |
8 | for(int i=1; i<=n; ++i) |
9 | win.push_back(i); |
10 | int num = 0; //开始报数 |
11 | while(win.size()>1){ |
12 | n = win.size(); |
13 | int len = 0; |
14 | for(int i=0; i<n; ++i){ |
15 | ++num; |
16 | if(num%k && num%10!=k) |
17 | win[len++] = win[i]; |
18 | } |
19 | if(len==0) win[len++] = win.back(); |
20 | win.resize(len); //重置个数 |
21 | } |
22 | cout << win[0] << endl; |
23 | return 0; |
24 | } |
201712-3 Crontab
1 | // CFF 201712-3 Crontab |
2 |
|
3 | using namespace std; |
4 | char vMon[][4]={"","jan","feb","mar","apr","may","jun","jul","aug","sep","oct","nov","dec"}; |
5 | char vWek[][4]={"sun","mon","tue","wed","thu","fri","sat"}; |
6 | int mtharray[]={0,31,28,31,30,31,30,31,31,30,31,30,31}; |
7 | map<string,int> mMon,mWek; |
8 | map<string,vector<string> > mrt; |
9 | void buildMonAndWekMap(){ //初始化月份和工作日对应的序号 |
10 | for(int i=1;i<=12;++i) mMon[vMon[i]]=i; |
11 | for(int i=0;i<=6;++i) mWek[vWek[i]]=i; |
12 | } |
13 | int stoi_x(const string &str){ //string转int |
14 | int ans; |
15 | stringstream ss(str); |
16 | ss>>ans; |
17 | return ans; |
18 | } |
19 | void toStandard(string &str){ //标准话:转化为小写 |
20 | int len=str.size(); |
21 | for(int i=0;i<len;++i) str[i]=tolower(str[i]); |
22 | } |
23 | string to_string_x(int n){ //int转string |
24 | stringstream ss; |
25 | ss<<n; |
26 | return ss.str(); |
27 | } |
28 | vector<string> splitStringAndbuildVector(string &str,int TAG){ //切分string构建vector |
29 | str+=","; |
30 | vector<string> vret; |
31 | size_t found=str.find(","); |
32 | while(found!=string::npos){ |
33 | string x=str.substr(0,found); |
34 | str=str.substr(found+1,str.size()-found-1); |
35 | size_t fdx=x.find("-"); |
36 | if(fdx==string::npos){ //非连续值 |
37 | if(TAG==1&&isalpha(x[0])) x=to_string_x(mMon[x]);//是month英文缩写,转换为数字 |
38 | if(TAG==2&&isalpha(x[0])) x=to_string_x(mWek[x]);//是day of week英文缩写,转换为数字 |
39 | if(x.size()==1) x="0"+x;//添加0 |
40 | vret.push_back(x); |
41 | }else{//连续值 |
42 | string L=x.substr(0,fdx),R=x.substr(fdx+1,x.size()-fdx-1); |
43 | int left,right; |
44 | if(TAG==0) left=stoi_x(L),right=stoi_x(R); |
45 | else if(TAG==1){//month |
46 | left=(isalpha(L[0]))?mMon[L]:stoi_x(L); |
47 | right=(isalpha(R[0]))?mMon[R]:stoi_x(R); |
48 | }else if(TAG==2){//day of week |
49 | left=(isalpha(L[0]))?mWek[L]:stoi_x(L); |
50 | right=(isalpha(R[0]))?mWek[R]:stoi_x(R); |
51 | } |
52 | while(left<=right){ |
53 | string num=to_string_x(left); |
54 | if(num.size()==1)num="0"+num; |
55 | vret.push_back(num); |
56 | ++left; |
57 | } |
58 | } |
59 | found=str.find(","); |
60 | } |
61 | return vret; |
62 | } |
63 | bool isleapyear(int y){ //判断是否闰年 |
64 | return (y%4==0&&y%100)||y%400==0; |
65 | } |
66 | string getWeekday(string year,string month,string day){ //计算星期几 |
67 | int y=stoi_x(year),m=stoi_x(month),d=stoi_x(day); |
68 | int by=1970,countday=0; |
69 | while(by<y){ |
70 | countday+=(isleapyear(by))?366:365; |
71 | ++by; |
72 | } |
73 | for(int i=1;i<m;++i) countday+=mtharray[i]; |
74 | countday+=d-1; |
75 | return "0"+to_string_x((4+countday%7)%7); |
76 | } |
77 | int main(){ |
78 | int n; |
79 | string st,et; |
80 | buildMonAndWekMap(); |
81 | cin>>n>>st>>et; |
82 | string syy=st.substr(0,4),smm=st.substr(4,2),sdd=st.substr(6,2),sHH=st.substr(8,2),sMM=st.substr(10,2); |
83 | string eyy=et.substr(0,4),emm=et.substr(4,2),edd=et.substr(6,2),eHH=et.substr(8,2),eMM=et.substr(10,2); |
84 | int syInt=stoi_x(syy),eyInt=stoi_x(eyy); |
85 | while(n--){ |
86 | vector<string> vmts,vhur,vdfm,vmth,vdfw; |
87 | string minutes,hours,dofmon,month,dofwek,command; |
88 | cin>>minutes>>hours>>dofmon>>month>>dofwek>>command; |
89 | toStandard(month);//不区别大小写,转化为标准小写 |
90 | toStandard(dofwek);//不区别大小写,转化为标准小写 |
91 | if(minutes=="*") minutes="0-59"; |
92 | vmts=splitStringAndbuildVector(minutes,0);//应该执行的分钟 |
93 | if(hours=="*") hours="0-23"; |
94 | vhur=splitStringAndbuildVector(hours,0); //应该执行的小时 |
95 | if(dofmon=="*") dofmon="1-31"; |
96 | vdfm=splitStringAndbuildVector(dofmon,0);//应该执行的日期 |
97 | if(month=="*") month="1-12"; |
98 | vmth=splitStringAndbuildVector(month,1);//应该执行的月份 |
99 | if(dofwek=="*") dofwek="0-6"; |
100 | vdfw=splitStringAndbuildVector(dofwek,2);//应该周几执行 |
101 | set<string> wekexist; |
102 | for(size_t i=0;i<vdfw.size();++i) wekexist.insert(vdfw[i]);//更快的检索当前日期(dayofweek)是不是应该执行 |
103 | int curyear=syInt;//从开始年份执行 |
104 | while(curyear<=eyInt){ |
105 | if(isleapyear(curyear)) mtharray[2]=29;//leapyear的2月份应该是29天 |
106 | else mtharray[2]=28; |
107 | string year=to_string_x(curyear);//年份 |
108 | for(size_t mi=0;mi<vmth.size();mi++){ //month |
109 | string curm=vmth[mi];//当前月份 |
110 | for(size_t di=0;di<vdfm.size();di++){ //day of month |
111 | string curd=vdfm[di];//当前日期 |
112 | string wd=getWeekday(year,curm,curd);//该年,该月,该日是星期几 |
113 | if(wekexist.count(wd)==0||stoi_x(curd)>mtharray[stoi_x(curm)])continue; |
114 | //命令行中不包含该星期或者当前天数超过当前月份的应有天数时 |
115 | for(size_t Hi=0;Hi<vhur.size();++Hi) //hour |
116 | for(size_t Mi=0;Mi<vmts.size();++Mi){ //minutes |
117 | string datetime=year+curm+curd+vhur[Hi]+vmts[Mi]; |
118 | if(datetime>=st&&datetime<et) mrt[datetime].push_back(command);//在当前日期时间内 |
119 | } |
120 | } |
121 | } |
122 | ++curyear;//进入下一年 |
123 | } |
124 | } |
125 | for(map<string,vector<string> >::iterator it=mrt.begin();it!=mrt.end();++it){ |
126 | map<string,int> isprt; |
127 | for(size_t i=0;i<it->second.size();++i){ |
128 | string dis=it->first+" "+it->second[i]; |
129 | if(isprt.count(dis)==0){ |
130 | cout<<dis<<endl; |
131 | isprt[dis]=1; |
132 | } |
133 | } |
134 | } |
135 | return 0; |
136 | } |
(学习参考:201712-3 Crontab ccf)
201712-4 行车路线
1 | //CCF 201712-4 行车路线 |
2 |
|
3 |
|
4 | using namespace std; |
5 | long long bigR[505][505], smallR[505][505]; //大路长度,小路长度 |
6 | long long tiredB[505], tiredS[505]; //大路的疲劳度,小路的疲劳度 |
7 | bool visited[505]; //经过路口:1为已经过 |
8 | int n, m; //路口数,道路数 |
9 | void floyd() { //预处理小路的连通性 |
10 | for(int k=1; k<=n; k++) |
11 | for(int i=1; i<=n; i++) |
12 | for(int j=1; j<=n; j++) |
13 | if(smallR[i][j]>smallR[i][k]+smallR[k][j] && smallR[i][k]!=INF && smallR[k][j]!=INF) |
14 | smallR[i][j] = smallR[i][k] + smallR[k][j]; |
15 | } |
16 | int main() { |
17 | memset(smallR, INF, sizeof(smallR)); |
18 | memset(bigR, INF, sizeof(bigR)); |
19 | cin >> n >> m; |
20 | for(int i=1; i<=m; i++) { |
21 | int t, a, b, c; //道路类型,起点路口,终点路口,道路长度 |
22 | cin>> t >> a >> b >> c; |
23 | if(t==1 && smallR[a][b]>c) //t==1 小道 |
24 | smallR[a][b] = smallR[b][a] = c; |
25 | else if(t==0 && bigR[a][b]>c) //t==0 大道 |
26 | bigR[a][b] = bigR[b][a] = c; |
27 | } |
28 | floyd(); |
29 | memset(tiredB, INF, sizeof(tiredB)); |
30 | memset(tiredS, INF, sizeof(tiredS)); |
31 | queue<int> q; //经过路口队列 |
32 | tiredB[1] = tiredS[1] = 0; //初始化大路小路的疲劳度 |
33 | q.push(1); |
34 | visited[1] = 1; |
35 | while(!q.empty()) { |
36 | int now = q.front(); |
37 | q.pop(); |
38 | visited[now] = 0; |
39 | for(int i=1; i<=n; i++) { //依次遍历n个路口 |
40 | long long v = bigR[now][i]; |
41 | if(tiredB[i] > tiredB[now]+v) { //大路加大路 |
42 | tiredB[i] = tiredB[now] + v; |
43 | if(visited[i]) continue; |
44 | visited[i] = 1; |
45 | q.push(i); |
46 | } |
47 | if(tiredB[i] > tiredS[now]+v) { //大路加小路 |
48 | tiredB[i] = tiredS[now]+v; |
49 | if(visited[i]) continue; |
50 | visited[i] = 1; |
51 | q.push(i); |
52 | } |
53 | if(smallR[now][i] < 1e10) { |
54 | v = smallR[now][i] * smallR[now][i]; |
55 | if(tiredS[i] > tiredB[now]+v) { //小路加大路 |
56 | tiredS[i] = tiredB[now]+v; |
57 | if(visited[i]) continue; |
58 | visited[i] = 1; |
59 | q.push(i); |
60 | } |
61 | } |
62 | } |
63 | } |
64 | cout << min(tiredB[n], tiredS[n]) << endl; |
65 | return 0; |
66 | } |
学习参考:
201712-5 商路
9月
201709-1 打酱油
1 | //CCF 201709-1 打酱油 |
2 |
|
3 | using namespace std; |
4 | int buy(int n){ |
5 | if(n<50) |
6 | return n<30 ? n/10 : 4+(n-30)/10; |
7 | return max(4+buy(n-30), 7+buy(n-50)); |
8 | } |
9 | int main(){ |
10 | int N; //小明的钱数 |
11 | cin >> N; |
12 | cout << buy(N) <<endl; |
13 | return 0; |
14 | } |
201709-2 公共钥匙盒
1 | //CCF 201709-2 公共钥匙盒 |
2 |
|
3 | using namespace std; |
4 | struct teacher{ |
5 | int num, s, e; //老师要使用的钥匙编号、开始上课的时间、上课的时长 |
6 | teacher(int x=0, int y=0, int z=0):num(x), s(y), e(z){} |
7 | }; |
8 | vector<teacher> p, q; |
9 | int keyN, teaN, key[1024]; //钥匙数、老师数、挂钩上的钥匙组 |
10 | bool cmpStart(const teacher &a, const teacher &b){ |
11 | return a.s < b.s; //比较开始使用时刻 |
12 | } |
13 | bool cmpStop(const teacher &a, const teacher &b){ |
14 | return a.e==b.e ? a.num<b.num : a.e<b.e; //比较使用的钥匙或使用时长 |
15 | } |
16 | int searchKeyPos(int keyId){ //搜索钥匙位置 |
17 | for(int i=1; i<=keyN; i++) |
18 | if(keyId == key[i]) return i; |
19 | cout << "can't find " << keyId << endl; |
20 | return -1; |
21 | } |
22 | int main(){ |
23 | cin >> keyN >> teaN; |
24 | for(int i=1; i<=keyN; i++) //初始化钥匙序号 |
25 | key[i] = i; |
26 | for(int i=0; i<teaN; i++){ //初始化老师使用钥匙情况 |
27 | teacher x; |
28 | cin >> x.num >> x.s >> x.e; |
29 | x.e += x.s; |
30 | p.push_back(x); |
31 | q.push_back(x); |
32 | } |
33 | sort(p.begin(), p.end(), cmpStart); //根据开始时间从小到大排 |
34 | sort(q.begin(), q.end(), cmpStop); //根据结束时间从小到大排 |
35 | int i=0, j=0; |
36 | while(i<teaN && j<teaN){ |
37 | if(p[i].s < q[j].e){ |
38 | int pos = searchKeyPos(p[i++].num); |
39 | key[pos] = -1; |
40 | } |
41 | else if(p[i].s >= q[j].e){ |
42 | int pos = searchKeyPos(-1); |
43 | key[pos] = q[j++].num; |
44 | } |
45 | } |
46 | while(j < teaN){ |
47 | int pos = searchKeyPos(-1); |
48 | key[pos] = q[j++].num; |
49 | } |
50 | for(int i=1; i<=keyN; i++) |
51 | cout << key[i] << " "; |
52 | return 0; |
53 | } |
201709-3 JSON查询
1 | // CFF 201709-3 JSON查询 |
2 |
|
3 | using namespace std; |
4 | bool IsRoot(string &json_str, size_t pos){ //判断是否为根元素 |
5 | int p_cnt = 0; |
6 | for(size_t i=0; i<pos; i++){ |
7 | if(json_str[i] == '{') p_cnt++; |
8 | if(json_str[i] == '}') p_cnt--; |
9 | } |
10 | return p_cnt==0; |
11 | } |
12 | vector<string> Split(string str){ //将字符串按'.'分割为字符串向量 |
13 | size_t pos = str.find("."); |
14 | vector<string> ret; |
15 | while(pos != string::npos){ |
16 | ret.push_back(str.substr(0, pos)); |
17 | str = str.substr(pos+1); |
18 | pos = str.find("."); |
19 | } |
20 | ret.push_back(str); |
21 | return ret; |
22 | } |
23 | string SubJsonStr(string json_str, int l_pos){ //返回子JSON串 |
24 | int p_cnt = 1; |
25 | size_t r_pos = l_pos; |
26 | while(p_cnt){ |
27 | if(json_str[r_pos]=='{') p_cnt++; |
28 | else if(json_str[r_pos]=='}') p_cnt--; |
29 | r_pos++; |
30 | } |
31 | return json_str.substr(l_pos, r_pos-l_pos-1) + ','; |
32 | } |
33 | void Search(vector<string> &ret, string json_str){ //JSON查询 |
34 | size_t i = 0; |
35 | while(i < ret.size()-1){ //依次遍历待查询JSON串向量的每一项 |
36 | size_t pos = json_str.find(ret[i]+":{"); |
37 | if(pos==string::npos || !IsRoot(json_str, pos)){ |
38 | cout << "NOTEXIST\n"; |
39 | return; |
40 | } |
41 | json_str = SubJsonStr(json_str, pos+ret[i].size()+2); |
42 | i++; |
43 | } |
44 | size_t pos = json_str.find(ret.back()+":"); |
45 | if(pos==string::npos || !IsRoot(json_str, pos)) |
46 | cout << "NOTEXIST\n"; |
47 | else{ |
48 | i = pos + ret.back().size() + 1; |
49 | if(json_str[i] == '{') cout << "OBJECT\n"; //是对象的情况 |
50 | else{ |
51 | size_t dp = json_str.find(",", i); |
52 | if(dp == string::npos){ |
53 | cout << "NOTEXIST\n"; |
54 | return; |
55 | } |
56 | string x; |
57 | while(i < dp) |
58 | x += json_str[i++]; |
59 | cout << "STRING " << x << endl; //是字符串的情况 |
60 | } |
61 | } |
62 | } |
63 | int main(){ |
64 | string json_str; //JSON字符串 |
65 | int n, m; |
66 | cin >> n >> m; |
67 | cin.get(); cin.get(); // '{' 与 '\n' |
68 | for(int i=0; i<n; i++){ |
69 | char ch; |
70 | while((ch=cin.get()) != '\n'){ |
71 | if(ch==' ' || ch=='"') continue; |
72 | if(ch == '\\'){ |
73 | json_str += cin.get(); //至包含一个 '\' |
74 | continue; |
75 | } |
76 | json_str += ch; |
77 | } |
78 | } |
79 | json_str[json_str.length()-1] = ','; |
80 | while(m--){ |
81 | string str; //待查询JSON字符串 |
82 | cin >> str; |
83 | vector<string> ret = Split(str); //将待查询JSON分割为字符串向量 |
84 | Search(ret, json_str); //JSON查询 |
85 | } |
86 | return 0; |
87 | } |
201709-4 通信网络
201709-5 除法
简单尝试的超时代码:
1 | // CFF 201709-5 除法 |
2 |
|
3 | using namespace std; |
4 | int l, r, v, sum = 0; //起点、终点、除数、和 |
5 | void doDivid(int n, int *a){ |
6 | cin >> l >> r >> v; |
7 | for(int i=l; i<=r; i++) |
8 | if(a[i]%v == 0) |
9 | a[i] /= v; |
10 | } |
11 | int getSum(int n, int a[]){ |
12 | cin >> l >> r; |
13 | for(int i=l; i<=r; i++) |
14 | sum += a[i]; |
15 | return sum; |
16 | } |
17 | int main(){ |
18 | int n, m; //数的个数和操作的次数 |
19 | cin >> n >> m; |
20 | int a[n+1]; //n个整数:下标为1~n |
21 | for(int i=1; i<=n; i++) |
22 | cin >> a[i]; |
23 | for(int i=0; i<m; i++){ |
24 | int opt; //操作标识 |
25 | cin >> opt; |
26 | if(opt == 1) //倍数做除法 |
27 | doDivid(n, a); |
28 | else if(opt == 2) //求和运算 |
29 | cout << getSum(n, a) << endl; |
30 | } |
31 | return 0; |
32 | } |
下面是上网学习到的树形数组
解决方案:源代码地址
1 | // CFF 201709-5 除法 |
2 |
|
3 | long long tree[101024]; //树形数组 |
4 | int n, m, a[101024]; //数的个数、操作的次数、一组数 |
5 | void update(int i, int val){ //更新树形数组 |
6 | while(i <= n){ |
7 | tree[i] += val; |
8 | i += -i & i; //i+(-i&i)是i的父节点,-i&i得出i末尾0的个数 |
9 | } |
10 | } |
11 | long long getsum(int i){ //求和 |
12 | long long sum = 0; |
13 | while(i > 0){ |
14 | sum += tree[i]; |
15 | i -= -i & i; //i-(-i&i)是前一个棵树的根节点 |
16 | } |
17 | return sum; |
18 | } |
19 | int main(){ |
20 | scanf("%d %d", &n, &m); |
21 | for(int i=1; i<=n; ++i){ |
22 | scanf("%d", &a[i]); |
23 | update(i, a[i]); |
24 | } |
25 | for(int i=1; i<=m; ++i){ |
26 | int opt, l, r, w; //操作标识、起点、终点、除数 |
27 | scanf("%d %d %d", &opt, &l, &r); |
28 | if(opt == 2) printf("%lld\n", getsum(r)-getsum(l-1)); |
29 | else{ |
30 | scanf("%d", &w); |
31 | if(w == 1) continue; |
32 | while(l <= r){ |
33 | if(a[l]>=w && a[l]%w==0){ |
34 | update(l, -(a[l]-a[l]/w)); |
35 | a[l] /= w; |
36 | } |
37 | ++l; |
38 | } |
39 | } |
40 | } |
41 | return 0; |
42 | } |
学习参考:
3月
201703-1 分蛋糕
1 | //CCF 201703-1 分蛋糕 |
2 |
|
3 | using namespace std; |
4 | int main(){ |
5 | int n, k; |
6 | int s = 0; //每个人依次分到蛋糕的总重量 |
7 | int i = 0; //已分配的蛋糕数量 |
8 | int w; //依次输入的每块蛋糕的重量 |
9 | int f = 0; //分到蛋糕的朋友数 |
10 | cin >> n >> k; |
11 | while(i<n){ |
12 | cin >> w; |
13 | ++i; |
14 | s = w; |
15 | while(i<n && s<k){ //当还有蛋糕并且此人分到蛋糕重量少于k |
16 | cin >> w; |
17 | s += w; |
18 | ++i; |
19 | } |
20 | ++f; |
21 | } |
22 | cout << f; |
23 | return 0; |
24 | } |
201703-2 学生排队
1 | // CCF 201703-2 学生排队 |
2 |
|
3 | using namespace std; |
4 | int n, m; |
5 | int mpos[1024], ran[1024]; //移动位置数组, 队伍排序数组 |
6 | void move(int pos, int len, int step){ //位置,长度,步长 |
7 | int temp = ran[pos]; |
8 | while(len){ |
9 | ran[pos] = ran[pos+step]; |
10 | mpos[ran[pos]] = pos; |
11 | pos += step; |
12 | --len; |
13 | } |
14 | mpos[temp] = pos; |
15 | ran[pos] = temp; |
16 | } |
17 | int main(){ |
18 | cin >> n >> m; |
19 | for(int i=1; i<=n; i++) |
20 | ran[i] = mpos[i] = i; //1-n做标记 |
21 | for(int i=0; i<m; i++){ |
22 | int id, val; //序号,移动数值 |
23 | cin >> id >> val; |
24 | int pos = mpos[id]; //开始移动的位置 |
25 | val<0 ? move(pos, -val, -1) : move(pos, val, 1); |
26 | } |
27 | for(int i=1; i<=n; i++) |
28 | cout << ran[i] << " "; |
29 | return 0; |
30 | } |
201703-3 Markdown
1 | //CCF 201703-3 Markdown |
2 |
|
3 | using namespace std; |
4 | int main(){ |
5 | string line, text; //Md文本行与html文本 |
6 | bool is_over = false; //判断是否结束 |
7 | getline(cin, line); //读取一行数据 |
8 | while(true){ |
9 | if(line.size()>0) text += line + "\n"; |
10 | else if(line.size()==0 && text.size()>0){ |
11 | size_t pos = text.find("_"); //强调文本 |
12 | while(pos != string::npos){ //用 <em> 替换 _ |
13 | text.replace(pos, 1, "<em>"); |
14 | size_t next_pos = text.find("_", pos); |
15 | text.replace(next_pos, 1, "</em>"); |
16 | pos = text.find("_", next_pos); |
17 | } |
18 | pos = text.find("["); |
19 | while(pos != string::npos){ //用 <a> 替换 []() |
20 | size_t next_pos = text.find("]", pos); |
21 | size_t left_pos = text.find("(", next_pos); |
22 | size_t right_pos = text.find(")", left_pos); |
23 | string text_for_link = text.substr(pos+1, next_pos-pos-1); //链接文本 |
24 | string link = text.substr(left_pos+1, right_pos-left_pos-1); //链接 |
25 | text.replace(text.begin()+pos, text.begin()+right_pos+1, "<a href=\""+link+"\">"+text_for_link+"</a>"); |
26 | pos = text.find("[", right_pos); |
27 | } |
28 | if(text[0] == '#'){ //用 <h1>标题</h1> 替换 # 标题 |
29 | int i = 0; |
30 | while(text[i]=='#') ++i; |
31 | text = text.substr(i+1); |
32 | text = "<h" + string(1, '0'+i) + ">" + text; |
33 | text.insert(text.size()-1, "</h"+string(1, '0'+i)+">"); |
34 | }else if(text[0] == '*'){ //用 <ul><li>组合 替换 * 列表 |
35 | text.insert(0, "<ul>\n"); |
36 | text.insert(text.size(), "</ul>\n"); |
37 | size_t pos = text.find("*"); |
38 | while(pos != string::npos){ //用 <li> 替换 * 列表项 |
39 | size_t next_pos = text.find("\n", pos); |
40 | text.insert(next_pos, "</li>"); |
41 | text.replace(pos, 2, "<li>"); |
42 | pos = text.find("*", next_pos); |
43 | } |
44 | }else{ //正常段落格式 <p>段落文本</p> |
45 | text = "<p>" + text; |
46 | text.insert(text.size()-1, "</p>"); |
47 | } |
48 | cout << text; |
49 | text = ""; |
50 | } |
51 | line = ""; |
52 | if(is_over) break; //结束 |
53 | if(!getline(cin, line)){ |
54 | is_over = true; |
55 | line = ""; |
56 | } |
57 | } |
58 | return 0; |
59 | } |
201703-4 地铁修建
1 | //CCF 201703-4 地铁修建 |
2 |
|
3 | using namespace std; |
4 | struct edge { |
5 | int u, v; //隧道的开始枢纽,终点枢纽 |
6 | int w; //建造所需时间 |
7 | edge(int a, int b, int c) : u(a), v(b), w(c){} |
8 | bool operator <(const edge &p) const { |
9 | return w < p.w; //自定义比较方式:比较建造所需时间 |
10 | } |
11 | }; //隧道的结构体 |
12 | vector<edge> tunnel; //隧道向量 |
13 | int n, m; //交通枢纽数,候选隧道数 |
14 | int company[100001]; //n个公司负责的枢纽 |
15 | int find(int x) { |
16 | return x==company[x] ? x : company[x]=find(company[x]); |
17 | } |
18 | int kruskal() { |
19 | for(int i=1; i<=n; i++) company[i] = i; |
20 | for(int i=0; i<m; i++) { |
21 | int x = find(tunnel[i].u), y = find(tunnel[i].v); |
22 | if(x != y) company[x] = y; |
23 | if(find(1) == find(n)) return tunnel[i].w; |
24 | } |
25 | return -1; |
26 | } |
27 | int main() { |
28 | cin >> n >> m; |
29 | for(int i=0; i<m; i++) { |
30 | int a, b, c; //枢纽a,枢纽b,a与b之间隧道建造的时间 |
31 | cin >> a >> b >> c; |
32 | tunnel.push_back(edge(a, b, c)); |
33 | } |
34 | sort(tunnel.begin(), tunnel.end()); //按照修建时间生序排列 |
35 | cout << kruskal(); |
36 | return 0; |
37 | } |
学习参考:
201703-5 引水入城
2016年
12月
201612-1 中间数
1 | //CCF 201612-1 中间数 |
2 |
|
3 | using namespace std; |
4 | int main(){ |
5 | int n; |
6 | cin >> n; |
7 | vector<int> v; |
8 | for(int i=0; i<n; ++i){ |
9 | int x; |
10 | cin >> x; |
11 | v.push_back(x); |
12 | } |
13 | sort(v.begin(), v.end()); |
14 | int j = v.size()/2, i = (v.size()%2==0) ? j-1 : j; |
15 | int e = v[j]; |
16 | while(i>=0 && j<n && v[i]==v[j] && v[i]==e) |
17 | --i, ++j; |
18 | if(i>=0 && (v[i]==e || v[j]==e)) |
19 | cout << -1; |
20 | else cout << e; |
21 | return 0; |
22 | } |
201612-2 工资计算
1 | //CCF 201612-2 工资计算 |
2 |
|
3 | using namespace std; |
4 | double rate[] = {0, 0.03, 0.1, 0.2, 0.25, 0.3, 0.35, 0.45}; |
5 | int v[]={3500,1500,3000,4500,26000,20000,25000}; |
6 | int u[]={3500,1500,3000,4500,26000,20000,25000}; |
7 | void cpt(){ //计算各个工资临界值的税费 |
8 | for(int i=1; i<7; ++i){ |
9 | u[i] += u[i-1]; //u的循环结果依次为各个临界工资值 |
10 | v[i] = v[i-1] + v[i]*(1-rate[i]); //v的循环结果依次为各个临界工资值对应的税费 |
11 | } |
12 | } |
13 | int main(){ |
14 | int t, i = 0; |
15 | cin >> t; |
16 | if(t <= 3500){ //税后所得少于3500,则S少于3500,即不交税 |
17 | cout << t <<endl; |
18 | return 0; |
19 | } |
20 | cpt(); //计算临界工资对应的税费 |
21 | while(v[i]<=t && i<7) ++i; |
22 | --i; |
23 | int s = u[i] + (t-v[i])/(1-rate[i+1]); //计算税前工资 |
24 | cout << s << endl; |
25 | return 0; |
26 | } |
201612-3 权限查询
1 | //CCF 201612-3 权限查询 |
2 |
|
3 | const int NOVALUE = -1; //不分等级 |
4 | const int TRUE = -2; |
5 | const int FALSE = -3; |
6 | using namespace std; |
7 | struct _privilege { //权限 |
8 | string category; |
9 | int level; |
10 | }; |
11 | vector<_privilege> privilege; |
12 | struct _role { //角色 |
13 | string role; |
14 | int s; |
15 | vector<_privilege> privilege; //每个角色有多个权限 |
16 | }; |
17 | vector<_role> role; |
18 | struct _user { //用户 |
19 | string user; |
20 | int t; |
21 | vector<string> role; //每个用户有多个角色 |
22 | }; |
23 | vector<_user> user; |
24 | string getcategory(string& s){ //得到权限类别 |
25 | int pos = s.find(":"); |
26 | if(pos == (int)string::npos) return s; |
27 | else return s.substr(0, pos); |
28 | } |
29 | int getlevel(string &s){ //得到权限等级 |
30 | int pos = s.find(":"); |
31 | if(pos == (int)string::npos) return NOVALUE; |
32 | else return atoi(s.substr(pos+1, s.length()-1).c_str()); |
33 | //atoi: 将string转换为int |
34 | } |
35 | int privilegematch(_privilege& p1, _privilege& p2){ //权限匹配 |
36 | if(p1.category != p2.category) return FALSE; |
37 | else if(p2.level == NOVALUE) { //不分等级查询 |
38 | if(p1.level == NOVALUE) return TRUE; |
39 | else return p1.level; |
40 | } else { //分等级查询 |
41 | if(p1.level == NOVALUE) return TRUE; |
42 | else { |
43 | if(p1.level >= p2.level) return TRUE; |
44 | else return FALSE; |
45 | } |
46 | } |
47 | } |
48 | int rolematch(string& rl, _privilege& prvl){ //角色匹配 |
49 | int ans = FALSE; |
50 | for(int i=0; i<(int)role.size(); i++) { |
51 | if(role[i].role == rl) { |
52 | for(int j=0; j<role[i].s; j++) { |
53 | int rt = privilegematch(role[i].privilege[j], prvl); |
54 | if(rt > ans) ans = rt; |
55 | } |
56 | } |
57 | } |
58 | return ans; |
59 | } |
60 | int query(string& usr, _privilege& prvl){ //查询用户权限 |
61 | for(int i=0; i<(int)user.size(); i++) { |
62 | if(user[i].user == usr) { |
63 | int ans = FALSE; |
64 | for(int j=0; j<user[i].t; j++) { |
65 | int rt = rolematch(user[i].role[j], prvl); |
66 | if(rt > ans) ans = rt; |
67 | } |
68 | return ans; |
69 | } |
70 | } |
71 | return FALSE; |
72 | } |
73 | int main(){ |
74 | int p, r, u, q; |
75 | cin >> p; //权限类别数量 |
76 | string c; //每个权限类别 |
77 | _privilege prvl; |
78 | for(int i=1; i<=p; i++) { |
79 | cin >> c; |
80 | prvl.category = getcategory(c); |
81 | prvl.level = getlevel(c); |
82 | privilege.push_back(prvl); |
83 | } |
84 | cin >> r; //角色数量 |
85 | for(int i=1; i<=r; i++) { |
86 | _role rl; |
87 | cin >> rl.role >> rl.s; |
88 | for(int j=1; j<=rl.s; j++) { |
89 | cin >> c; |
90 | prvl.category = getcategory(c); |
91 | prvl.level = getlevel(c); |
92 | rl.privilege.push_back(prvl); |
93 | } |
94 | role.push_back(rl); |
95 | } |
96 | cin >> u; //用户数量 |
97 | for(int i=1; i<=u; i++) { //输入每个用户 |
98 | _user us; |
99 | cin >> us.user >> us.t; |
100 | for(int j=1; j<=us.t; j++) { |
101 | cin >> c; |
102 | us.role.push_back(c); |
103 | } |
104 | user.push_back(us); |
105 | } |
106 | cin >> q; //查询数量 |
107 | string suser; //每个授权查询 |
108 | for(int i=1; i<=q; i++) { |
109 | cin >> suser >> c; //查询用户、权限 |
110 | prvl.category = getcategory(c); |
111 | prvl.level = getlevel(c); |
112 | int ans = query(suser, prvl); |
113 | if(ans == TRUE) cout << "true" << endl; |
114 | else if(ans == FALSE) cout << "false" << endl; |
115 | else cout << ans << endl; |
116 | } |
117 | return 0; |
118 | } |
学习参考:201612-3 权限查询
201612-4 压缩编码
201612-5 卡牌游戏
9月
201609-1 最大波动
1 | //CCF 201609-1 最大波动 |
2 |
|
3 | using namespace std; |
4 | int main(){ |
5 | int n, max = 0; |
6 | cin >> n; |
7 | int a[n]; |
8 | cin >> a[0]; |
9 | for(int i=1; i<n; i++){ |
10 | cin >> a[i]; |
11 | int tmp = abs(a[i]-a[i-1]); |
12 | max = max > tmp ? max : tmp; |
13 | } |
14 | cout << max << endl; |
15 | return 0; |
16 | } |
201609-2 火车购票
1 | // CFF 201609-2 火车购票 |
2 |
|
3 | using namespace std; |
4 | int main(){ |
5 | int n; |
6 | cin >> n; |
7 | vector<int> v(20, 5); //一节车厢有20排、每一排5个座位 |
8 | for(int i=0; i<n; i++){ |
9 | int x; |
10 | cin >> x; //输入要购入的票数 |
11 | for(int r=0; r<20&&x>0; r++) //逐行查找 |
12 | if(v[r] >= x){ //该行空余座位大于需求x |
13 | int seat = r*5+5-v[r]+1; //给空闲座位编号 |
14 | v[r] -= x; //x个已购,更新空余座位 |
15 | while(x--){ |
16 | cout << seat++; |
17 | if(x>0) cout << " "; |
18 | else cout << endl; |
19 | } |
20 | } |
21 | if(x>0) //没有连续座位 |
22 | for(int r=0; r<20&&x>0; r++) |
23 | while(v[r]>0 && x>0){ |
24 | int seat = r*5+5-v[r]+1; |
25 | cout << seat++; |
26 | --v[r]; |
27 | --x; |
28 | if(x>0) cout << " "; |
29 | else cout << endl; |
30 | } |
31 | } |
32 | return 0; |
33 | } |
201609-3 炉石传说
1 | // CCF 201609-3 炉石传说 |
2 |
|
3 | using namespace std; |
4 | struct role{ |
5 | int attack, health; //每个角色的攻击力和健康值 |
6 | role(int ak, int ht):attack(ak), health(ht){} |
7 | }; |
8 | vector<role> va, vb; //两个角色vector |
9 | int n, turn = 0; //操作个数、转换回合标志 |
10 | void display(vector<role> &v){ //输出生命值、随从个数等信息 |
11 | cout << v[0].health << endl; |
12 | cout << v.size()-1; |
13 | for(size_t i=1; i<v.size(); i++) |
14 | cout << " " << v[i].health; |
15 | cout << endl; |
16 | } |
17 | int main(){ |
18 | va.push_back(role(0,30)); |
19 | vb.push_back(role(0,30)); |
20 | cin >> n; |
21 | for(int i=0; i<n; i++){ |
22 | string action; //每个操作 |
23 | cin >> action; |
24 | if(action == "summon"){ //召唤随从 |
25 | int pos, ak, ht; //位置、攻击力、健康值 |
26 | cin >> pos >> ak >> ht; |
27 | if(turn==0) va.insert(va.begin()+pos,role(ak,ht)); |
28 | else vb.insert(vb.begin()+pos,role(ak,ht)); |
29 | }else if(action=="end") //结束该回合 |
30 | turn = (turn+1)%2; |
31 | else if(action=="attack"){ //攻击 |
32 | int i, j; //发起攻击的随从号、被攻击的对方角色号 |
33 | cin >> i >> j; |
34 | if(turn==0){ |
35 | va[i].health -= vb[j].attack; |
36 | vb[j].health -= va[i].attack; |
37 | if(va[i].health<=0&&i) |
38 | va.erase(va.begin()+i); |
39 | if(vb[j].health<=0&&j) |
40 | vb.erase(vb.begin()+j); |
41 | }else{ |
42 | vb[i].health -= va[j].attack; |
43 | va[j].health -= vb[i].attack; |
44 | if(va[j].health<=0&&j) |
45 | va.erase(va.begin()+j); |
46 | if(vb[i].health<=0&&i) |
47 | vb.erase(vb.begin()+i); |
48 | } |
49 | } |
50 | if(va[0].health<=0 || vb[0].health<=0) |
51 | break; |
52 | } |
53 | if(va[0].health<=0&&vb[0].health>0) //后手玩家胜 |
54 | cout << -1 << endl; |
55 | else if(va[0].health>0&&vb[0].health<=0) //先手玩家胜 |
56 | cout << 1 << endl; |
57 | else cout << 0 << endl; //游戏尚未结束 |
58 | display(va); |
59 | display(vb); |
60 | return 0; |
61 | } |
201609-4 交通规划
1 | //CCF 201609-4 交通规划 |
2 |
|
3 | using namespace std; |
4 | const int INF = 0x7fffffff; |
5 | int n, m; //城市数,铁路数 |
6 | struct edge { |
7 | int v; |
8 | int cost; |
9 | edge(int x, int c) : v(x), cost(c){} |
10 | }; |
11 | struct cmp { |
12 | bool operator()(edge &a, edge &b) { |
13 | return a.cost > b.cost; |
14 | } |
15 | }; |
16 | vector<edge> vg[10000]; |
17 | int main() { |
18 | cin >> n >> m; |
19 | for(int i=0; i<m; i++) { |
20 | int a, b, c; //城市a,城市b,a与b之间双向铁路的长度 |
21 | cin >> a >> b >> c; |
22 | --a, --b; |
23 | vg[a].push_back(edge(b, c)); |
24 | vg[b].push_back(edge(a, c)); |
25 | } |
26 | //dijkstra |
27 | priority_queue<edge,vector<edge>,cmp> pq; |
28 | vector<int> dist(n, INF); |
29 | vector<int> cost(n, INF); |
30 | vector<bool> visit(n, 0); |
31 | pq.push(edge(0, 0)); |
32 | dist[0] = cost[0] = 0; |
33 | while(!pq.empty()) { |
34 | edge t = pq.top(); //最短路径(花费)边 |
35 | pq.pop(); |
36 | visit[t.v] = 1; //访问该节点 |
37 | for(size_t i=0; i<vg[t.v].size(); i++) { |
38 | edge e = vg[t.v][i]; //该节点的所有邻接边 |
39 | if(visit[e.v]) continue; //另外一端节点访问过了,跳过 |
40 | if(dist[e.v] > dist[t.v]+e.cost) { //更新最短路径 |
41 | dist[e.v] = dist[t.v] + e.cost; |
42 | cost[e.v] = e.cost; |
43 | pq.push(edge(e.v, dist[e.v])); //新的更新边 |
44 | } |
45 | else if(dist[e.v] == dist[t.v]+e.cost) |
46 | cost[e.v] = min(cost[e.v], e.cost); |
47 | } |
48 | } |
49 | int sum = 0; |
50 | for(int i=0; i<n; i++) |
51 | sum += cost[i]; |
52 | cout << sum << endl; |
53 | return 0; |
54 | } |
学习参考:
201609-5 祭坛
4月
201604-1 折点计数
1 | // CFF 201604-1 折点计数 |
2 |
|
3 | using namespace std; |
4 | int main(){ |
5 | int n, num = 0; |
6 | cin >> n; |
7 | int a[n]; |
8 | cin >> a[0] >> a[1]; |
9 | for(int i=2; i<n; i++){ |
10 | cin >> a[i]; |
11 | if((a[i-2]>a[i-1] && a[i-1]<a[i]) || (a[i-2]<a[i-1] && a[i-1]>a[i])) |
12 | num++; |
13 | } |
14 | cout << num << endl; |
15 | return 0; |
16 | } |
201604-2 俄罗斯方块
1 | // CCF 201604-2 俄罗斯方块 |
2 |
|
3 | using namespace std; |
4 | const int ROW = 15; //方格图行数 |
5 | const int COL = 10; //方格图列数 |
6 | const int N = 4; //新方块阶数 |
7 | int board[ROW+1][COL]; //初始方格图,最下面一行全为1 |
8 | int block[N][N]; //新方块 |
9 | struct { int row, col; } coords[N]; //新方块的模式块数组 |
10 | int main(){ |
11 | int row, col; |
12 | // 输入数据 |
13 | for(int i=0; i<ROW; i++) |
14 | for(int j=0; j<COL; j++) |
15 | cin >> board[i][j]; |
16 | for(int i=0; i<N; i++) |
17 | for(int j=0; j<N; j++) |
18 | cin >> block[i][j]; |
19 | cin >> col; |
20 | // 底边全放1 |
21 | for(int j=0; j<COL; j++) |
22 | board[ROW][j] = 1; |
23 | // 提取新方块的模式块坐标 |
24 | int k = 0; |
25 | for(int i=N-1; i>=0; i--) |
26 | for(int j=0; j<N; j++) |
27 | if(block[i][j] == 1) { |
28 | coords[k].row = i; |
29 | coords[k].col = j; |
30 | k++; |
31 | } |
32 | // 模拟新方块落下过程 |
33 | row = 1, col--; |
34 | bool checkflag; |
35 | while(true){ |
36 | checkflag = false; |
37 | for(int i=0; i<N; i++) |
38 | if(board[row + coords[i].row][col + coords[i].col] == 1) { |
39 | checkflag = true; |
40 | break; |
41 | } |
42 | if(checkflag) break; |
43 | row++; |
44 | } |
45 | row--; |
46 | // 合并新方块到方格图 |
47 | for(int i=0; i<N; i++) |
48 | board[row + coords[i].row][col + coords[i].col] = 1; |
49 | // 输出结果 |
50 | for(int i=0; i<ROW; i++) { |
51 | for(int j=0; j<COL; j++) { |
52 | if(j != 0) cout << " "; |
53 | cout << board[i][j]; |
54 | } |
55 | cout << endl; |
56 | } |
57 | return 0; |
58 | } |
201604-3 路径解析
1 | // CCF 201604-3 路径解析 |
2 |
|
3 | using namespace std; |
4 | int main(){ |
5 | int n; //路径个数 |
6 | string curDir; //当前目录 |
7 | cin >> n >> curDir; |
8 | getchar(); |
9 | for(int i=0; i<n; i++){ |
10 | string line; //每一个待处理路径 |
11 | getline(cin, line); |
12 | size_t pos; |
13 | //添加当前目录 |
14 | if(line[0] != '/') line = curDir + '/' + line; |
15 | if(line.size() == 0) line = curDir; |
16 | //除去多个'///' |
17 | while((pos = line.find("//")) != -1){ |
18 | int count = 2; // '/'的个数 |
19 | while(line[pos + count] == '/') count++; |
20 | line.erase(pos, count-1); |
21 | } |
22 | //除去'../' |
23 | while((pos = line.find("/../")) != -1){ |
24 | if(pos == 0) line.erase(pos+1, 3); |
25 | else{ |
26 | size_t nxp = line.rfind("/", pos-1); |
27 | line.erase(nxp, pos-nxp+3); |
28 | } |
29 | } |
30 | while((pos = line.find("/./")) != -1) //除去'./' |
31 | line.erase(pos+1, 2); |
32 | if(line.size()>1 && line[line.size()-1]=='/') //除去末尾'/' |
33 | line.erase(line.size()-1); |
34 | cout << line << endl; |
35 | } |
36 | return 0; |
37 | } |
201604-4 游戏
201604-5 网络连接
2015年
12月
201512-1 数位之和
1 | // CFF 201512-1 数位之和 |
2 |
|
3 | using namespace std; |
4 | int main(){ |
5 | int n, sum = 0; |
6 | cin >> n; |
7 | while(n>0){ |
8 | int t = n%10; |
9 | sum += t; |
10 | n /= 10; |
11 | } |
12 | cout << sum << endl; |
13 | return 0; |
14 | } |
15 | |
16 | // CFF 201512-1 数位之和——改进版 |
17 |
|
18 | using namespace std; |
19 | int main(){ |
20 | char x; |
21 | int sum=0; |
22 | while((x=getchar()) != '\n') |
23 | sum += x-'0'; |
24 | cout << sum; |
25 | return 0; |
26 | } |
201512-2 消除类游戏
1 | //CCF 201512-2 消除类游戏 |
2 |
|
3 | using namespace std; |
4 | int n, m, a[30][30]; |
5 | int main(){ |
6 | //输入数据 |
7 | cin >> n >> m; |
8 | for(int i=0; i<n; i++) |
9 | for(int j=0; j<m; j++) |
10 | cin >> a[i][j]; |
11 | //行可消除的标记为负 |
12 | for(int i=0; i<n; i++) |
13 | for(int j=0; j<m-2; j++) |
14 | if(abs(a[i][j])==abs(a[i][j+1]) && abs(a[i][j+1])==abs(a[i][j+2])){ |
15 | if(a[i][j] > 0) a[i][j] *= -1; |
16 | if(a[i][j+1] > 0) a[i][j+1] *= -1; |
17 | if(a[i][j+2] > 0) a[i][j+2] *= -1; |
18 | } |
19 | //列可消除的标记为负 |
20 | for(int j=0; j<m; j++) |
21 | for(int i=0; i<n-2; i++) |
22 | if(abs(a[i][j])==abs(a[i+1][j]) && abs(a[i+1][j])==abs(a[i+2][j])){ |
23 | if(a[i][j] > 0) a[i][j] *= -1; |
24 | if(a[i+1][j] > 0) a[i+1][j] *= -1; |
25 | if(a[i+2][j] > 0) a[i+2][j] *= -1; |
26 | } |
27 | //完成消除 |
28 | for(int i=0; i<n; i++){ |
29 | for(int j=0; j<m; j++){ |
30 | if(a[i][j] < 0) a[i][j] = 0; |
31 | if(j != 0) cout << " "; |
32 | cout << a[i][j]; |
33 | } |
34 | cout << endl; |
35 | } |
36 | return 0; |
37 | } |
201512-3 画图
1 | //CCF 201512-3 画图 |
2 |
|
3 | using namespace std; |
4 | const int DIRECTSIZE = 4; |
5 | struct direct { |
6 | int dx, dy; |
7 | } direct[DIRECTSIZE] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}}; |
8 | const int N = 100; |
9 | char grid[N+1][N+1]; //画布 |
10 | void fill(int x, int y, char c, int m, int n){ //递归填充:被填充的点的四周也要填充 |
11 | int nx, ny; |
12 | grid[y][x] = c; |
13 | for(int i=0; i<DIRECTSIZE; i++) { |
14 | ny = y + direct[i].dy; |
15 | nx = x + direct[i].dx; |
16 | if(0<=nx && nx<m && 0<=ny && ny<n && grid[ny][nx]!='|' |
17 | && grid[ny][nx]!='-' && grid[ny][nx]!='+' && grid[ny][nx]!=c) |
18 | fill(nx, ny, c, m, n); |
19 | } |
20 | } |
21 | int main(){ |
22 | int m, n, q; //画布的宽度、高度、画图操作个数 |
23 | int x1, y1, x2, y2; //坐标 |
24 | int start, end; //线段起点和终点 |
25 | memset(grid, '.', sizeof(grid)); // 变量初始化:全部设置为“.” |
26 | cin >> m >> n >> q; |
27 | for(int i=1; i<=q; i++) { //依次完成q个画图操作 |
28 | int option; //每行的画图形式 |
29 | cin >> option; |
30 | if(option == 0) { //画线段 |
31 | cin >> x1 >> y1 >> x2 >> y2; |
32 | if(x1 == x2) { |
33 | start = min(y1, y2); |
34 | end = max(y1, y2); |
35 | for(int j=start; j<=end; j++) |
36 | if(grid[j][x1] == '-' || grid[j][x1] == '+') |
37 | grid[j][x1] = '+'; |
38 | else grid[j][x1] = '|'; |
39 | } else if(y1 == y2) { |
40 | start = min(x1, x2); |
41 | end = max(x1, x2); |
42 | for(int j=start; j<=end; j++) |
43 | if(grid[y1][j] == '|' || grid[y1][j] == '+') |
44 | grid[y1][j] = '+'; |
45 | else grid[y1][j] = '-'; |
46 | } |
47 | } else if(option == 1) { //填充字符 |
48 | char c; //填充字符 |
49 | cin >> x1 >> y1 >> c; |
50 | fill(x1, y1, c, m, n); //递归填充 |
51 | } |
52 | } |
53 | for(int i=n-1; i>=0; i--) { |
54 | for(int j=0; j<m; j++) |
55 | cout << grid[i][j]; |
56 | cout << endl; |
57 | } |
58 | return 0; |
59 | } |
学习参考:201512-3 画图
201512-4 送货
201512-5 矩阵
9月
201509-1 数列分段
1 | // CFF 201509-1 数列分段 |
2 |
|
3 | using namespace std; |
4 | int main(){ |
5 | int n, s = 1; |
6 | cin >> n; |
7 | int a[n]; |
8 | cin >> a[0]; |
9 | for(int i=1; i<n; i++){ |
10 | cin >> a[i]; |
11 | if(a[i]!=a[i-1]) |
12 | s++; |
13 | } |
14 | cout << s << endl; |
15 | return 0; |
16 | } |
201509-2 日期计算
1 | // CCF 201509-2 日期计算 |
2 |
|
3 | using namespace std; |
4 | int main(){ |
5 | int y, d, k = 0; |
6 | cin >> y >> d; |
7 | int limit[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; |
8 | if(y%400==0 || (y%4==0&&y%100)) //是闰年 |
9 | limit[1] = 29; |
10 | for(int i=1; i<12; i++) // 每月的临界天数 |
11 | limit[i] += limit[i-1]; |
12 | while(d > limit[k]) |
13 | k++; |
14 | int month = k + 1, day = d - limit[k-1]; |
15 | cout << month << endl << day << endl; |
16 | return 0; |
17 | } |
201509-3 模板生成系统
1 | //CCF 201509-3 模板生成系统 |
2 |
|
3 | using namespace std; |
4 | int main(){ |
5 | int n, m; |
6 | cin >> n >> m; |
7 | cin.get(); |
8 | string str_in, str_out; //输入和输出的字符串 |
9 | map<string, string> mmp; //需要处理的map键值对 |
10 | while(n--){ |
11 | string line; |
12 | getline(cin, line); |
13 | str_in += line + '\n'; |
14 | } |
15 | while(m--){ |
16 | string key, val; //map的键与值 |
17 | cin >> key; |
18 | cin.get(); |
19 | getline(cin, val); |
20 | val = val.substr(1, val.size()-2); |
21 | mmp[key] = val; |
22 | } |
23 | size_t pos, next_pos; |
24 | while((pos=str_in.find("{{ ")) != string::npos){ //完成值的填充 |
25 | next_pos = str_in.find(" }}") + 3; |
26 | string key(str_in.begin()+pos+3, str_in.begin()+next_pos-3); |
27 | str_out += str_in.substr(0, pos); |
28 | str_in = str_in.substr(next_pos); |
29 | string var = mmp.count(key) ? mmp[key] : ""; |
30 | str_out += var; |
31 | } |
32 | str_out += str_in; |
33 | cout << str_out; |
34 | return 0; |
35 | } |
201509-4 高速公路
201509-5 最佳文章
3月
201503-1 图像旋转
1 | // CFF 201503-1 图像旋转 |
2 |
|
3 | using namespace std; |
4 | int a[1024][1024]; |
5 | int main(){ |
6 | int n, m; |
7 | cin >> n >> m; |
8 | for(int i=0; i<n; i++) |
9 | for(int j=0; j<m; j++) |
10 | cin >> a[i][j]; |
11 | for(int j=m-1; j>=0; j--){ |
12 | for(int i=0; i<n; i++) |
13 | cout << a[i][j] << " "; |
14 | cout << endl; |
15 | } |
16 | return 0; |
17 | } |
201503-2 数字排序
1 | // CCF 201503-2 数字排序 |
2 |
|
3 | using namespace std; |
4 | int n, a[1024]; //整数个数与整数序列 |
5 | struct node{ |
6 | int id, cnt; //每个整数的序号和出现次数值 |
7 | node(int a, int b):id(a), cnt(b){} |
8 | }; |
9 | vector<node> v; //node结构体类型的vector |
10 | bool cmp(const node &a, const node &b){ //次数相同时候升序为真 |
11 | return a.cnt==b.cnt ? a.id<b.id : a.cnt>b.cnt; |
12 | } |
13 | int main(){ |
14 | cin >> n; |
15 | for(int i=0; i<n; i++){ |
16 | int t; |
17 | cin >> t; |
18 | a[t]++; |
19 | } |
20 | for(int i=0; i<=1000; i++) |
21 | if(a[i]) v.push_back(node(i, a[i])); |
22 | sort(v.begin(), v.end(), cmp); //自定义比较规则cmp排序 |
23 | for(size_t i=0; i<v.size(); i++) //size_t: unsigned int类型的别名 |
24 | cout << v[i].id << " " << v[i].cnt << endl; |
25 | return 0; |
26 | } |
201503-3 节日
1 | //CCF 201503-3 节日 |
2 |
|
3 | using namespace std; |
4 | int month[] = {-1, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; //不是闰年 |
5 | bool IsLeapYear(int y){ //判断是否是闰年 |
6 | return (y%400==0)||(y%4==0&&y%100); |
7 | } |
8 | int HowManyDays(int s, int y, int m){ //计算s年1月1日离y年m月1日有多少天 |
9 | int days = 0; |
10 | while(s < y) days += IsLeapYear(s++) ? 366 : 365; |
11 | if(IsLeapYear(y)) month[2] = 29; |
12 | for(int i=1; i<m; i++) days += month[i]; |
13 | return days; |
14 | } |
15 | int WhichDayInWeek(int w, int b, int c){ //第b个星期c是几号 |
16 | int day = 1; |
17 | while(w != c){ |
18 | day++; |
19 | w++; |
20 | if(w == 8) w = 1; |
21 | } |
22 | return day + 7*(b-1); |
23 | } |
24 | int main(){ |
25 | int a, b, c, y1, y2; //a月第b个星期c、起始年份、终止年份 |
26 | cin >> a >> b >> c >> y1 >> y2; |
27 | for(int year=y1; year<=y2; year++){ |
28 | int w = (HowManyDays(1850, year, a)+2)%7; //y1-y2每年a月1日是星期几 |
29 | if(w == 0) w = 7; |
30 | int day = WhichDayInWeek(w, b, c); //求出是a月的几号 |
31 | if(day > month[a]) cout << "none" << endl; |
32 | else printf("%d/%02d/%02d\n", year, a, day); |
33 | month[2] = 28; |
34 | } |
35 | return 0; |
36 | } |
201503-4 网络延时
1 | //CCF 201503-4 网络延时 |
2 |
|
3 | using namespace std; |
4 | vector<int> v[20018]; |
5 | int n, m; |
6 | void dfs(int u, int depth, int &maxdepth, int &maxdepvertex, bool visit[]) { |
7 | visit[u] = 1; |
8 | if(depth > maxdepth) { |
9 | maxdepth = depth; |
10 | maxdepvertex = u; |
11 | } |
12 | for(size_t i=0; i<v[u].size(); i++) { |
13 | int w = v[u][i]; //u的邻接点 |
14 | if(!visit[w]) |
15 | dfs(w, depth+1, maxdepth, maxdepvertex, visit); |
16 | } |
17 | } |
18 | int main() { |
19 | cin >> n >> m; //交换机数,终端电脑数 |
20 | for(int i=2; i<=n; i++) { |
21 | int x; //第2~n台交换机连接的上一层交换机的编号 |
22 | cin >> x; |
23 | v[x].push_back(i); |
24 | v[i].push_back(x); |
25 | } |
26 | for(int i=1; i<=m; i++) { |
27 | int x; //第1~m台终端连接的交换机的编号 |
28 | cin >> x; |
29 | v[x].push_back(10000+i); |
30 | v[10000+i].push_back(x); |
31 | } |
32 | bool v1[20018] = {0}, v2[20018] = {0}; //visit数组 |
33 | int maxdepth = -1, maxdepvertex = -1; |
34 | dfs(1, 0, maxdepth, maxdepvertex, v1); |
35 | dfs(maxdepvertex, 0, maxdepth, maxdepvertex, v2); |
36 | cout << maxdepth; |
37 | return 0; |
38 | } |
学习参考:201503-4 网络延时 ccf
201503-5 最小花费
2014年
12月
201412-1 门禁系统
1 | // CFF 201412-1 门禁系统 |
2 |
|
3 | using namespace std; |
4 | int main(){ |
5 | int n; |
6 | cin >> n; |
7 | int cnt[1024] = {0}; //每条记录依次出现的实时次数 |
8 | int a[1024] = {0}; //每条记录第几次出现 |
9 | for(int i=0; i<n; i++){ |
10 | int x; |
11 | cin >> x; |
12 | cnt[x]++; |
13 | a[i] = cnt[x]; |
14 | } |
15 | for(int i=0; i<n; i++) |
16 | cout << a[i] << " "; |
17 | return 0; |
18 | } |
201412-2 Z字形扫描
1 | //CCF 201412-2 Z字形扫描 |
2 |
|
3 | using namespace std; |
4 | int n, a[500][500]; |
5 | int main(){ |
6 | cin >> n; |
7 | for(int i=0; i<n; i++) |
8 | for(int j=0; j<n; j++) |
9 | cin >> a[i][j]; |
10 | for(int i=0; i<2*n-1; i++){ //一共有 2*n-1 条斜线 |
11 | int s = i<n ? 0 : (i-n+1); |
12 | int e = i<n ? i : (n-1); |
13 | if(i%2 == 0) //第i条斜线编号是偶数: 从左下打印到右上 |
14 | for(int j=s; j<=e; j++) |
15 | cout << a[i-j][j] << " "; |
16 | else //第i条斜线编号是奇数: 从右上打印到左下 |
17 | for(int j=s; j<=e; j++) |
18 | cout << a[j][i-j] << " "; |
19 | } |
20 | cout << endl; |
21 | return 0; |
22 | } |
201412-3 集合竞价
1 | //CCF 201412-3 集合竞价 |
2 |
|
3 | using namespace std; |
4 | const int N = 5000; //交易行数最大值 |
5 | struct trading { //交易 |
6 | int orderno; //交易编号 |
7 | char t; //买(buy)、卖(sell)标志,取值为b、s |
8 | float price; //价格 |
9 | long long quantity; //数量 |
10 | bool operator < (const trading& n) const { // < 操作符重载 |
11 | if(t == 's') return price > n.price; |
12 | else return price < n.price; // t == 'b' |
13 | } |
14 | }; |
15 | bool canceltrading[N+1]; //标记是否撤销了第i行交易记录 |
16 | int main(){ |
17 | //初始化与输入部分 |
18 | trading t; |
19 | string strading; //每一行交易操作 |
20 | int tradingno = 0, cancelno; //交易号码、撤销的交易号 |
21 | priority_queue<trading> sell, buy; //卖、买两个优先队列:数字大的优先级高 |
22 | memset(canceltrading, false, sizeof(canceltrading)); //变量初始化 |
23 | while(cin >> strading) { |
24 | if(strading[0] == 'c') { //撤销交易 |
25 | tradingno++; |
26 | cin >> cancelno; |
27 | canceltrading[cancelno] = true; //设置撤销标志 |
28 | } else if(strading[0] == 'b' || strading[0] == 's') { |
29 | t.orderno = ++tradingno; |
30 | cin >> t.price >> t.quantity; |
31 | if(strading[0] == 'b') { //将交易放入买入的优先队列 |
32 | t.t = strading[0]; |
33 | buy.push(t); |
34 | } else { //将交易放入卖出的优先队列 |
35 | t.t = strading[0]; |
36 | sell.push(t); |
37 | } |
38 | } else break; |
39 | } |
40 | //集合竞价处理部分 |
41 | t.price = 0; //开盘价 |
42 | t.quantity = 0; //此开盘价下的成交量 |
43 | trading b, s; |
44 | while(true) { |
45 | while(!buy.empty()) { //清除被取消的buy订单 |
46 | b = buy.top(); //b为买队列的队头 |
47 | if(canceltrading[b.orderno]) buy.pop(); |
48 | else break; |
49 | } |
50 | while(!sell.empty()) { //清除被取消的sell订单 |
51 | s = sell.top(); //s为卖队列的队头 |
52 | if(canceltrading[s.orderno]) sell.pop(); |
53 | else break; |
54 | } |
55 | if(buy.empty() || sell.empty()) break; //买卖队列只要有一个为空就结束 |
56 | if(b.price >= s.price) { //买卖交易开始处理 |
57 | t.quantity += min(b.quantity, s.quantity); |
58 | t.price = b.price; |
59 | if(b.quantity == s.quantity) { |
60 | buy.pop(); |
61 | sell.pop(); |
62 | } else if(b.quantity > s.quantity) { |
63 | b.quantity -= s.quantity; |
64 | buy.pop(); |
65 | buy.push(b); |
66 | sell.pop(); |
67 | } else { |
68 | buy.pop(); |
69 | s.quantity -= b.quantity; |
70 | sell.pop(); |
71 | sell.push(s); |
72 | } |
73 | } else break; |
74 | } |
75 | // 输出结果部分 |
76 | printf("%.2f", t.price); |
77 | cout << " " << t.quantity << endl; |
78 | return 0; |
79 | } |
学习参考:
201412-4 最优灌溉
1 | //CCF 201412-4 最优灌溉 |
2 |
|
3 | using namespace std; |
4 | const int INF = 1061109567; |
5 | int mmp[1010][1010]; //各个麦田之间的水渠费用map |
6 | int lowdist[1010]; //最小花费数组 |
7 | int visit[1010]; //建水渠的麦田数组 1:建 0:不建 |
8 | void prim(int n){ //Prim算法(最小生成树算法) |
9 | for(int i=1; i<=n; i++) |
10 | lowdist[i] = mmp[1][i]; |
11 | visit[1] = 1; |
12 | int k, sum = 0; //sum为总费用 |
13 | for(int i=1; i<n; i++){ |
14 | int min_val = INF; //动态变化的最小费用 |
15 | for(int j=1; j<=n; j++) |
16 | if(!visit[j] && lowdist[j] < min_val){ |
17 | min_val = lowdist[j]; |
18 | k = j; |
19 | } |
20 | visit[k] = 1; |
21 | sum += min_val; |
22 | for(int j=1; j<=n; j++) |
23 | if(!visit[j] && mmp[k][j] < lowdist[j]) |
24 | lowdist[j] = mmp[k][j]; |
25 | } |
26 | cout << sum; |
27 | } |
28 | int main(){ |
29 | int n, m; //麦田数、可建的水渠数 |
30 | cin >> n >> m; |
31 | memset(mmp, INF, sizeof(mmp)); //将mmp的内容全设为INF |
32 | memset(visit, 0, sizeof(visit)); //初始化所有麦田不建水渠 |
33 | for(int i=0; i<m; i++){ |
34 | int start, end, value; //水渠起点、终点以及费用 |
35 | cin >> start >> end >> value; |
36 | if(mmp[start][end] > value) |
37 | mmp[start][end] = mmp[end][start] = value; |
38 | } |
39 | prim(n); |
40 | return 0; |
41 | } |
学习参考:最小生成树Prim算法理解
201412-5 货物调度
9月
201409-1 相邻数对
1 | // 201409-1 相邻数对 |
2 |
|
3 | using namespace std; |
4 | int main(){ |
5 | int n, num = 0; |
6 | cin >> n; |
7 | int a[n]; |
8 | for(int i=0; i<n; i++) |
9 | cin >> a[i]; |
10 | sort(a, a+n); |
11 | for(int i=1; i<n; i++){ |
12 | if(a[i]-a[i-1] == 1) |
13 | num++; |
14 | } |
15 | cout << num <<endl; |
16 | return 0; |
17 | } |
201409-2 画图
1 | // CCF 201409-2 画图 |
2 |
|
3 | using namespace std; |
4 | int main(){ |
5 | int n, xy[100][100] = {0}; //矩形个数、坐标系大小 |
6 | cin >> n; |
7 | int x1, y1, x2, y2, sum = 0; //每个矩形的坐标、颜色方块数 |
8 | for(int i=0; i<n; i++){ //处理每一个矩形 |
9 | cin >> x1 >> y1 >> x2 >> y2; |
10 | for(int j=x1; j<x2; j++) |
11 | for(int k=y1; k<y2; k++) |
12 | if(!xy[j][k]){ //避免重复 |
13 | sum++; |
14 | xy[j][k] = 1; |
15 | } |
16 | } |
17 | cout << sum << endl; |
18 | return 0; |
19 | } |
201409-3 字符串匹配
1 | //CCF 201409-3 字符串匹配 |
2 |
|
3 | using namespace std; |
4 | int main(){ |
5 | string str; //待匹配字符串、输出文本 |
6 | int is_dif, n; //大小写敏感标识符、文本行数 |
7 | cin >> str >> is_dif >> n; |
8 | while(n--){ |
9 | string new_str; //每一行识别文本 |
10 | cin >> new_str; |
11 | if(is_dif == 1){ //大小写敏感 |
12 | size_t pos = new_str.find(str); |
13 | if(pos != string::npos) |
14 | cout << new_str << endl; |
15 | }else{ //大小写不敏感: 全转化为小写再匹配 |
16 | string tmp, txt; //临时的str、new_str |
17 | for(size_t i=0; i<str.size(); i++) |
18 | tmp += tolower(str[i]); |
19 | for(size_t i=0; i<new_str.size(); i++) |
20 | txt += tolower(new_str[i]); |
21 | size_t pos = txt.find(tmp); |
22 | if(pos != string::npos) |
23 | cout << new_str << endl; |
24 | } |
25 | } |
26 | return 0; |
27 | } |
201409-4 最优配餐
1 | //CCF 201409-4 最优配餐 |
2 |
|
3 | using namespace std; |
4 | const int N = 1000; |
5 | const int DIRECTSIZE = 4; |
6 | struct direct { //前进方向 |
7 | int drow, dcol; |
8 | } direct[DIRECTSIZE] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}}; |
9 | int buyer[N+1][N+1]; //客户坐标下的订餐量 |
10 | int visited[N+1][N+1]; //经过的点坐标 1:不可再经过 0:可经过 |
11 | int buyercount = 0; //客户数量 |
12 | long long ans = 0; //最终送餐费用 |
13 | struct node { |
14 | int row, col, step; |
15 | node(){} |
16 | node(int r, int c, int s){row=r, col=c, step=s;} |
17 | }; |
18 | queue<node> q; //分店节点队列 |
19 | void bfs(int n){ //广度优先搜索 |
20 | node front, v; |
21 | while(!q.empty()){ |
22 | front = q.front(); |
23 | q.pop(); |
24 | for(int i=0; i<DIRECTSIZE; i++){ |
25 | //移动一格 |
26 | v.row = front.row + direct[i].drow; |
27 | v.col = front.col + direct[i].dcol; |
28 | v.step = front.step + 1; |
29 | //行列越界则跳过 |
30 | if(v.row<1 || v.row>n || v.col<1 || v.col>n) continue; |
31 | // 已经访问过的点不再访问 |
32 | if(visited[v.row][v.col]) continue; |
33 | // 如果是订餐点,则计算成本并且累加 |
34 | if(buyer[v.row][v.col] > 0) { |
35 | visited[v.row][v.col] = 1; |
36 | ans += buyer[v.row][v.col] * v.step; |
37 | if(--buyercount == 0) return; |
38 | } |
39 | // 向前搜索:标记v点为已经访问过,v点加入队列中 |
40 | visited[v.row][v.col] = 1; |
41 | q.push(v); |
42 | } |
43 | } |
44 | } |
45 | int main(){ |
46 | int n, m, k, d; //方格图大小、分店数、客户数、禁止通行点的数量 |
47 | int x, y, c; //分店/客户/禁止点坐标与订餐量 |
48 | memset(buyer, 0, sizeof(buyer)); |
49 | memset(visited, 0, sizeof(visited)); |
50 | cin >> n >> m >> k >> d; |
51 | for(int i=1; i<=m; i++){ //依次输入分店坐标 |
52 | cin >> x >> y; |
53 | q.push(node(x, y, 0)); |
54 | visited[x][y] = 1; |
55 | } |
56 | for(int i=1; i<=k; i++){ //依次输入客户坐标 |
57 | cin >> x >> y >> c; |
58 | if(buyer[x][y]==0) |
59 | buyercount++; |
60 | buyer[x][y] += c; |
61 | } |
62 | for(int i=1; i<=d; i++){ //依次输入禁止通行的点 |
63 | cin >> x >> y; |
64 | visited[x][y] = 1; |
65 | } |
66 | bfs(n); |
67 | cout << ans << endl; |
68 | return 0; |
69 | } |
学习参考:
201409-5 拼图
3月
201403-1 相反数
1 | // 201403-1 相反数 |
2 |
|
3 | using namespace std; |
4 | int main(){ |
5 | int n, num = 0; |
6 | cin >> n; |
7 | int a[1024] = {0}; |
8 | for(int i=0; i<n; i++){ |
9 | int x; |
10 | cin >> x; |
11 | a[abs(x)]++; |
12 | } |
13 | for(int i=0; i<1000; i++){ |
14 | if(a[i]==2) |
15 | num++; |
16 | } |
17 | cout << num <<endl; |
18 | return 0; |
19 | } |
201403-2 窗口
1 | //CCF 201403-2 窗口 |
2 |
|
3 | using namespace std; |
4 | struct window{ |
5 | int x1, y1, x2, y2, num; //窗口位置坐标、窗口序号 |
6 | window(int a=0,int b=0,int c=0,int d=0,int x=0):x1(a),y1(b),x2(c),y2(d),num(x){} |
7 | }; |
8 | vector<window> v; |
9 | bool check(int x, int y, window &w){ //检查(x, y)是否在窗口w上 |
10 | return (x>=w.x1 && y>=w.y1 && x<=w.x2 && y<=w.y2) ? true : false; |
11 | } |
12 | int todo(int x, int y){ |
13 | size_t i = 0; |
14 | while(i < v.size()){ |
15 | if(check(x, y, v[i])){ |
16 | window temp = v[i]; |
17 | v.erase(v.begin()+i); //删除第i项 |
18 | v.insert(v.begin(), temp); //重新插入 |
19 | cout << temp.num << endl; |
20 | return 0; |
21 | } |
22 | i++; |
23 | } |
24 | cout << "IGNORED\n"; |
25 | } |
26 | int main(){ |
27 | int n, m; //n个窗口、m次点击操作 |
28 | cin >> n >> m; |
29 | v.resize(n); |
30 | for(int i=n-1; i>=0; i--){ //依次建立各个窗口结构体 |
31 | int x1, y1, x2, y2; |
32 | cin >> x1 >> y1 >> x2 >> y2; |
33 | v[i] = window(x1, y1, x2, y2, n-i); |
34 | } |
35 | while(m--){ //依次执行操作 |
36 | int x, y; |
37 | cin >> x >> y; |
38 | todo(x, y); |
39 | } |
40 | return 0; |
41 | } |
201403-3 命令行选项
1 | //CCF 201403-3 命令行选项 |
2 |
|
3 | using namespace std; |
4 | const int N = 256; |
5 | char delimiter[] = " "; //字符串分割符 |
6 | void spilt(vector<string>& v, char *s, char *t){ |
7 | char *sp; |
8 | sp = strtok(s, t); //字符串切割函数,参数为字符串和分割符 |
9 | while(sp) { |
10 | v.push_back(sp); |
11 | sp = strtok(NULL, t); //第一次用一个字符串做第一个参数,以后用NULL做第一个参数 |
12 | } |
13 | } |
14 | void mygetline(char *pc){ |
15 | char c; |
16 | while((c=getchar()) != '\n' && c !=EOF) |
17 | *pc++ = c; |
18 | *pc = '\0'; |
19 | } |
20 | int main(){ |
21 | string format; //命令格式 |
22 | int n; //命令行数 |
23 | char s[N+1]; //每行命令 |
24 | cin >> format >> n; |
25 | getchar(); |
26 | for(int i=1; i<=n; i++) { // 输入n行命令行进行处理 |
27 | vector<string> sv; //分割后的命令行片段vector |
28 | map<string, string> m; |
29 | mygetline(s); // 输入命令行 |
30 | spilt(sv, s, delimiter); // 切分命令行:命令和各个参数分开 |
31 | for(int j=1; j<(int)sv.size(); j++) { // 处理各个参数,放入map变量m中 |
32 | if(sv[j].size() == 2 && sv[j][0] == '-') { // 判断是否是选项,选项则处理 |
33 | int pos = format.find(sv[j][1]); |
34 | if(pos == -1) // 选项在格式中未找到则出错结束 |
35 | break; |
36 | if(m.find(sv[j]) == m.end()) // 选项未出现过则添加 |
37 | m[sv[j]] = ""; |
38 | if(format[pos+1] == ':' && j+1 < (int)sv.size()) { // 更新参数:后出现优先 |
39 | m[sv[j]] = sv[j+1]; |
40 | j++; |
41 | } |
42 | } else |
43 | break; |
44 | } |
45 | // 输出结果 |
46 | cout << "Case " << i << ":"; |
47 | for(map<string,string>::iterator iter=m.begin(); iter!=m.end(); iter++) { |
48 | cout << " " << iter->first; |
49 | if(iter->second != "") |
50 | cout << " " << iter->second; |
51 | } |
52 | cout << endl; |
53 | } |
54 | return 0; |
55 | } |
201403-4 无线网络
1 | //CCF CCF201403-4 无线网络 |
2 |
|
3 | using namespace std; |
4 | const int MAXN = 100 + 100; //路由器最大数量 |
5 | struct { long long x, y; } coord[MAXN+1]; //n+m个路由器的坐标结构数组 |
6 | struct status { |
7 | long long x, y; |
8 | int step, kcount; //步数,可连接路由器数 |
9 | }; |
10 | bool visited[MAXN+1]; //已访问过的路由器设置为true |
11 | int router(int n, int m, int k, int begin, int end, long long r){ |
12 | int max; |
13 | memset(visited, false, sizeof(visited)); |
14 | status start, front, v; //开始路由器,队头路由器,访问路由器 |
15 | start.x = coord[begin].x; //设置根结点start |
16 | start.y = coord[begin].y; |
17 | start.step = 0; |
18 | start.kcount = 0; |
19 | queue<status> q; //路由器访问队列 |
20 | q.push(start); |
21 | visited[begin] = true; |
22 | while(!q.empty()) { |
23 | front = q.front(); //依次出队列访问 |
24 | q.pop(); |
25 | if(front.x==coord[end].x && front.y==coord[end].y) //到达终点 结束 |
26 | return front.step - 1; |
27 | if(front.kcount == k) max = n; //搜索可以连接的路由器 |
28 | else max = n + m; |
29 | for(int i=0; i<max; i++) { |
30 | if(visited[i]) continue; |
31 | if((front.x-coord[i].x)*(front.x-coord[i].x)+(front.y-coord[i].y)*(front.y-coord[i].y) > r*r) |
32 | continue; //判定下一个路由器坐标是否在半径r之内,不在则跳过,在则继续搜索 |
33 | else { |
34 | visited[i] = true; |
35 | //计算步数,并且将第i个路由器加入队列 |
36 | v.x = coord[i].x; |
37 | v.y = coord[i].y; |
38 | v.step = front.step + 1; |
39 | if(i >= n) |
40 | v.kcount = front.kcount + 1; |
41 | else |
42 | v.kcount = front.kcount; |
43 | q.push(v); |
44 | } |
45 | } |
46 | } |
47 | return 0; |
48 | } |
49 | int main() { |
50 | int n, m, k; //已放置路由器数,可再放置的位置数,新增路由器最大数 |
51 | long long r; //确保网络间连接的最大距离 |
52 | cin >> n >> m >> k >> r; |
53 | for(int i=0; i<n+m; i++) //依次输入原路由器和新增路由器的位置 |
54 | cin >> coord[i].x >> coord[i].y; |
55 | cout << router(n, m, k, 0, 1, r) << endl; |
56 | return 0; |
57 | } |
201403-5 任务调度
2013年
12月
201312-1 出现次数最多的数
1 | //CCF 201312-1 出现次数最多的数 |
2 |
|
3 | using namespace std; |
4 | int main(){ |
5 | int n, maxval = -1; |
6 | cin >> n; |
7 | int a[10001] = {0}; |
8 | for(int i=0; i<n; i++){ |
9 | int t; |
10 | cin >> t; |
11 | a[t]++; |
12 | } |
13 | for(int i=1; i<=10000; i++) |
14 | maxval = max(maxval, a[i]); |
15 | for(int i=1; i<=10000; i++) |
16 | if(maxval == a[i]){ |
17 | cout << i << endl; |
18 | break; |
19 | } |
20 | return 0; |
21 | } |
201312-2 ISBN号码
1 | // CCF 201312-2 ISBN号码 |
2 |
|
3 | using namespace std; |
4 | char valX(int s){ |
5 | return s%11==10 ? 'X' : '0'+s%11; //数字转字符: +'0' |
6 | } |
7 | int main(){ |
8 | int sum = 0, i = 1, j = 0; |
9 | char str[16], ch; |
10 | while((ch=cin.get()) != '\n'){ |
11 | str[j++] = ch; |
12 | if(isdigit(ch)){ |
13 | if(i<=9) sum += i*(ch-'0'); //字符转数字: -'0' |
14 | i++; |
15 | } |
16 | } |
17 | str[j] = '\0'; //空字符表示字符串末尾 |
18 | char x = valX(sum); |
19 | if(str[j-1] == x) |
20 | cout << "Right\n"; |
21 | else{ |
22 | str[j-1] = x; |
23 | printf("%s\n", str); |
24 | } |
25 | return 0; |
26 | } |
201312-3 最大的矩形
1 | // CCF 201312-3 最大的矩形 |
2 |
|
3 | using namespace std; |
4 | int main(){ |
5 | int n, ans = -1, height[1024]; //矩阵个数、最大矩形面积、矩形高度数组 |
6 | cin >> n; |
7 | for(int i=1; i<=n; i++) |
8 | cin >> height[i]; |
9 | for(int i=1; i<=n; i++){ |
10 | int min_height = height[i]; |
11 | for(int j=i+1; j<=n; j++){ |
12 | min_height = min(min_height, height[j]); |
13 | ans = max(min_height*(j-i+1), ans); |
14 | } |
15 | } |
16 | cout << ans << endl; |
17 | return 0; |
18 | } |
201312-4 有趣的数
1 | // CCF 201312-4 有趣的数 |
2 | /* 方法一:组合数学的思路:(假设0、1、2、3分别有a、b、c、d个) |
3 | (1)0在1前面且不在首位:a+b-1种 |
4 | (2)2和3其中一个在首位,假设是2在首位。将剩余c-1个2和d个3插入已经放好的a+b+1个数中, |
5 | 即:把c+d-1个相同球放入a+b+1个相同的盒子(可空)中,即C(a+b+1+c+d-1-1,c+d-1)种 |
6 | (3)2和3一共有c+d-1种 |
7 | 故总共有: C(a+b+1+c+d-1-1,c+d-1) * (a+b-1) * (c+d-1)种 |
8 | */ |
9 |
|
10 |
|
11 | using namespace std; |
12 | long long MOD=1000000007, n, s[MAX][MAX], ans=0; |
13 | int main(){ |
14 | for(int i=1; i<MAX; i++) |
15 | s[i][i]=1, s[i][1]=i, s[i][0]=1; |
16 | for(int i=2; i<MAX; i++) |
17 | for(int j=1; j<i; j++) |
18 | s[i][j] = (s[i-1][j-1]+s[i-1][j]) % MOD; |
19 | cin >> n; |
20 | for(int i=2; i<=n-2; i++){ |
21 | ans = (ans+s[n-1][i-1]*(i-1)*(n-i-1)) % MOD; |
22 | } |
23 | cout << ans << endl; |
24 | return 0; |
25 | } |
26 | /* 方法二:动态规划 |
27 | 题目给出了0,1,2,3四个数,现考察一系列中间状态,即选取四个数的子集,在满足题设条件下,共有如下6种状态 |
28 | 状态0:2 |
29 | 状态1:0 2 |
30 | 状态2:2 3 |
31 | 状态3:0 1 2 |
32 | 状态4:0 2 3 |
33 | 状态5:0 1 2 3 |
34 | 最终我们需要求得的结果是状态5,用sta[i][j]表示一系列中间过程,其中i表示数的位数,j表示状态 |
35 | 显然,i=0时,所有的不同结果都为0(边界条件) |
36 | 对于状态0来说,所选取的集合只有2,所以对于任意数位n,其不同个数始终为1 |
37 | 对于状态1来说,数位为i时的结果可以通过第i-1位状态获得,包括 |
38 | (1)通过状态0获得,只能在第i位时添加0,即sta[i-1][0] |
39 | (2)通过本身状态1获得,在第i位添加0或者2,即sta[i-1][1]*2 |
40 | 所以,sta[i][1]=sta[i-1][0]+sta[i-1][1]*2 |
41 | 对于状态2来说,数位为i时的结果可以通过第i-1位状态获得,包括 |
42 | (1)通过状态0获得,只能在第i位时添加3,即sta[i-1][0] |
43 | (2)通过本身状态2获得,只能在第i位添加3,即sta[i-1][2] |
44 | 所以,sta[i][2]=sta[i-1][0]+sta[i-1][2] |
45 | 其余状态同理,也即是,对于任意状态,总可以通过前序状态或者本身状态获得 |
46 | 所有转移方程如下 |
47 | sta[i][0]=1 |
48 | sta[i][1]=sta[i-1][0]+sta[i-1][1]*2 |
49 | sta[i][2]=sta[i-1][0]+sta[i-1][2] |
50 | sta[i][3]=sta[i-1][1]+sta[i-1][3]*2 |
51 | sta[i][4]=sta[i-1][1]+sta[i-1][2]+sta[i-1][4]*2 |
52 | sta[i][5]=sta[i-1][3]+sta[i-1][4]+sta[i-1][5]*2 |
53 | 对状态的补充: |
54 | 一个数情况,必须是2(首位必须是2) |
55 | (0)2 |
56 | 两个数情况,必须有2,其余只能是0,3(0必须在1前面) |
57 | (1)0 2 |
58 | (2)2 3 |
59 | 三个数情况,必须有2,其余可能是0,1或者0,3 |
60 | (3)0 1 2 |
61 | (4)0 2 3 |
62 | 四个数情况,(5)0 1 2 3 |
63 | 6种状态整理完毕 |
64 | */ |
65 |
|
66 | using namespace std; |
67 | long long mod=1000000007, sta[1024][6], n; |
68 | int main(){ |
69 | scanf("%lld", &n); |
70 | for(long long i=1; i<=n; i++){ |
71 | sta[i][0] = 1; |
72 | sta[i][1] = (sta[i-1][0]+sta[i-1][1]*2) % mod; |
73 | sta[i][2] = (sta[i-1][0]+sta[i-1][2]) % mod; |
74 | sta[i][3] = (sta[i-1][1]+sta[i-1][3]*2) % mod; |
75 | sta[i][4] = (sta[i-1][1]+sta[i-1][2]+sta[i-1][4]*2) % mod; |
76 | sta[i][5] = (sta[i-1][3]+sta[i-1][4]+sta[i-1][5]*2) % mod; |
77 | } |
78 | printf("%lld\n", sta[n][5]); |
79 | return 0; |
80 | } |
学习参考: