AcWing 3212. 图像旋转
旋转是图像处理的基本操作,在这个问题中,你需要将一个图像逆时针旋转 90 度。
计算机中的图像表示可以用一个矩阵来表示,为了旋转一个图像,只需要将对应的矩阵旋转即可。
输入格式
输入的第一行包含两个整数 n,m,分别表示图像矩阵的行数和列数。
接下来 n 行每行包含 m 个整数,表示输入的图像。
输出格式
输出 m 行,每行包含 n 个整数,表示原始矩阵逆时针旋转 90 度后的矩阵。
数据范围
1≤n,m≤1,000
矩阵中的数都是不超过 1000 的非负整数。输入样例
2 3 1 5 3 3 2 4
输出样例
3 4 5 2 1 3
画完图之后直接暴力枚举即可 AC:
#include<iostream>
using namespace std;
const int N=1e3+5;
int n,m,a[N][N];
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) cin>>a[i][j];
for(int j=m;j>=1;j--){
for(int i=1;i<=n;i++){
cout<<a[i][j]<<" ";
}
cout<<endl;
}
return 0;
}
AcWing 3213. 数字排序
给定 n 个整数,请统计出每个整数出现的次数,按出现次数从多到少的顺序输出。
输入格式
输入的第一行包含一个整数 n,表示给定整数的个数。
第二行包含 n 个整数,相邻的整数之间用一个空格分隔,表示所给定的整数。
输出格式
输出多行,每行包含两个整数,分别表示一个给定的整数和它出现的次数。
按出现次数递减的顺序输出。如果两个整数出现的次数一样多,则先输出值较小的,然后输出值较大的。
数据范围
1≤n≤1000
给出的数都是不超过 1000 的非负整数。输入样例
12 5 2 3 3 1 3 4 2 5 2 3 5
输出样例
3 4 2 3 5 3 1 1 4 1
map(去重并且计数)+vector(存答案方便排序操作)+sort(按照次数升序排序) AC:
#include<iostream>
#include<map>
#include<vector>
#include<algorithm>
using namespace std;
int n;
map<int,int>num;
vector<pair<int,int>>ans;
bool cmp(pair<int,int>x,pair<int,int>y){
if(x.second==y.second) return x.first<y.first;
return x.second>y.second;
}
int main(){
cin>>n;
for(int i=1;i<=n;i++){
int t;
cin>>t;
num[t]++;
}
for(auto x:num) ans.push_back(x);
sort(ans.begin(),ans.end(),cmp);
for(auto x:ans) cout<<x.first<<" "<<x.second<<endl;
return 0;
}
AcWing 3214. 节日
有一类节日的日期并不是固定的,而是以“a 月的第 b 个星期 c”的形式定下来的,比如说母亲节就定为每年的五月的第二个星期日。
现在,给你 a,b,c 和 y1,y2,希望你输出从公元 y1 年到公元 y2 年间的每年的 a 月的第 b 个星期 c 的日期。
提示:关于闰年的规则:年份是 400 的整数倍时是闰年,否则年份是 4 的倍数并且不是 100 的倍数时是闰年,其他年份都不是闰年。
例如 1900 年就不是闰年,而 2000 年是闰年。
为了方便你推算,已知 1850 年 1 月 1 日是星期二。
输入格式
输入包含恰好一行,有五个整数 a,b,c,y1,y2。
其中 c=1,2,……,6,7 分别表示星期一、二、……、六、日。
输出格式
对于 y1 和 y2 之间的每一个年份,包括 y1 和 y2,按照年份从小到大的顺序输出一行。
如果该年的 a 月第 b 个星期 c 确实存在,则以
yyyy/mm/dd
的格式输出,即输出四位数的年份,两位数的月份,两位数的日期,中间用斜杠/
分隔,位数不足时前补零。如果该年的 a 月第 b 个星期 c 并不存在,则输出
none
。数据范围
1≤a≤12
1≤b≤5
1≤c≤7
1850≤y1,y2≤2050输入样例
5 2 7 2014 2015
输出样例
2014/05/11 2015/05/10
日期问题 模拟AC:
#include<iostream>
using namespace std;
int a,b,c,y1,y2,flag[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
bool isLeapYear(int y){
return ((y%400==0)||(y%4==0&&y%100!=0));
}
int weekSince1850(int year,int month,int day) {
int week=1;
for(int y=1850;y<year;y++){
week+=365+isLeapYear(y);
week%=7;
}
for(int m=1;m<month;m++) {
week+=flag[m]+(m==2&&isLeapYear(year));
week%=7;
}
week+=day;
week%=7;
return week;
}
int main(){
cin>>a>>b>>c>>y1>>y2;
c%=7;
for(int y=y1;y<=y2;y++){
bool key=false;
int m=a;
bool leap=(m==2&&isLeapYear(y));
int cnt=0;
for(int d=1;d<=flag[m]+leap;d++){
if(weekSince1850(y,m,d)==c) cnt++;
if(cnt==b) {printf("%d/%02d/%02d\n",y,m,d); key=true; break;}
}
if(!key) cout<<"none"<<endl;
}
return 0;
}
AcWing 3215. 网络延时
给定一个公司的网络,由 n 台交换机和 m 台终端电脑组成,交换机与交换机、交换机与电脑之间使用网络连接。
交换机按层级设置,编号为 1 的交换机为根交换机,层级为 1。
其他的交换机都连接到一台比自己上一层的交换机上,其层级为对应交换机的层级加 1。
所有的终端电脑都直接连接到交换机上。
当信息在电脑、交换机之间传递时,每一步只能通过自己传递到自己所连接的另一台电脑或交换机。
请问,电脑与电脑之间传递消息、或者电脑与交换机之间传递消息、或者交换机与交换机之间传递消息最多需要多少步。
输入格式
输入的第一行包含两个整数 n,m,分别表示交换机的台数和终端电脑的台数。
第二行包含 n−1 个整数,分别表示第 2、3、……、n 台交换机所连接的比自己上一层的交换机的编号。第 i 台交换机所连接的上一层的交换机编号一定比自己的编号小。
第三行包含 m 个整数,分别表示第 1、2、……、m 台终端电脑所连接的交换机的编号。
输出格式
输出一个整数,表示消息传递最多需要的步数。
数据范围
前 30% 的评测用例满足:n≤5,m≤5
前 50% 的评测用例满足:n≤20,m≤20
前 70% 的评测用例满足:n≤100,m≤100
所有评测用例都满足:1≤n≤10000,1≤m≤10000输入样例1
4 2 1 1 3 2 1
输出样例1
4
样例1解释
样例的网络连接模式如下,其中圆圈表示交换机,方框表示电脑:
其中电脑 1 与交换机 4 之间的消息传递花费的时间最长,为 4 个单位时间。
输入样例2
4 4 1 2 2 3 4 4 4
输出样例2
4
样例2解释
样例的网络连接模式如下:
其中电脑 1 与电脑 4 之间的消息传递花费的时间最长,为 4 个单位时间。
在做这题前先复习道关于 树的直径 模板题:
核心思路是:以任意点出发,找到距离该点最远的2条路径,加起来就是直径
AcWing 1072. 树的最长路径
给定一棵树,树中包含 n 个结点(编号1~n)和 n−1 条无向边,每条边都有一个权值。
现在请你找到树中的一条最长路径。
换句话说,要找到一条路径,使得使得路径两端的点的距离最远。
注意:路径中可以只包含一个点。
输入格式
第一行包含整数 n。
接下来 n−1 行,每行包含三个整数 ai,bi,ci,表示点 ai 和 bi 之间存在一条权值为 ci 的边。
输出格式
输出一个整数,表示树的最长路径的长度。
数据范围
1≤n≤10000
1≤ai,bi≤n
−10^5≤ci≤10^5输入样例
6 5 1 6 1 4 5 6 3 9 2 6 8 6 1 7
输出样例
22
树的最长路径 AC:
#include<iostream>
#include<vector>
using namespace std;
const int N=1e4+5;
int n,ans;
vector<pair<int,int>>G[N];
int dfs(int u,int father){
int d1=0,d2=0; //分别用于存储当前节点的最长和次长路径长度
for(auto t:G[u]){
int point=t.first,val=t.second;
if(point==father) continue;//避免回到父节点
int d=dfs(point,u)+val; //计算从邻接节点出发的最长路径长度,并加上边权
//更新最长和次长路径长度
if(d>=d1) d2=d1,d1=d;
else if(d>d2) d2=d;
}
ans=max(ans,d1+d2);
return d1;
}
int main(){
cin>>n;
for (int i=1;i<n;i++){
int a,b,c;
cin>>a>>b>>c;
G[a].push_back(make_pair(b,c));
G[b].push_back(make_pair(a,c));
}
dfs(1,-1);//从节点1开始搜索,没有父节点,所以传-1
cout<<ans<<endl;
return 0;
}
网络延时 AC:
#include<iostream>
#include<vector>
using namespace std;
const int N=2e4+5;
int n,m,ans;
vector<int>G[N];
int dfs(int u,int father){
int d1=0,d2=0;
for(auto t:G[u]){
if(t==father) continue;
int d=dfs(t,u)+1;
if(d>=d1) d2=d1,d1=d;
else if(d>d2) d2=d;
}
ans=max(ans,d1+d2);
return d1;
}
int main(){
cin>>n>>m;
for(int i=2;i<=n;i++){
int j;cin>>j;
G[i].push_back(j);
G[j].push_back(i);
}
for(int i=n+1;i<=n+m;i++){
int j;cin>>j;
G[i].push_back(j);
G[j].push_back(i);
}
dfs(1,-1);
cout<<ans<<endl;
return 0;
}
AcWing 3216. 最小花费
C 国共有 n 个城市,编号 1∼n。
有 n−1 条双向道路,每条道路连接两个城市,任意两个城市之间能互相到达。
小 R 来到 C 国旅行,他共规划了 m 条旅行的路线,第 i 条旅行路线的起点是 si,终点是 ti。
在旅行过程中,小 R 每行走一单位长度的路需要吃一单位的食物。
C 国的食物只能在各个城市中买到,而且不同城市的食物价格可能不同。
然而,小 R 不希望在旅行中为了购买较低价的粮食而绕远路,因此他总会选择最近的路走。
现在,请你计算小 R 规划的每条旅行路线的最小花费是多少。
输入格式
第一行包含 2 个整数 n 和 m。
第二行包含 n 个整数。第 i 个整数 wi 表示城市 i 的食物价格。
接下来 n−1 行,每行包括 3 个整数 u,v,e,表示城市 u 和城市 v 之间有一条长为 e 的双向道路。
接下来 m 行,每行包含 2 个整数 si 和 ti,分别表示一条旅行路线的起点和终点。
输出格式
输出 m 行,分别代表每一条旅行方案的最小花费。
数据范围
前 10% 的评测用例满足:n,m≤20,wi≤20
前 30% 的评测用例满足:n,m≤200
另有 40% 的评测用例满足:一个城市至多与其它两个城市相连
所有评测用例都满足:1≤n,m≤10^5,1≤wi≤10^6,1≤e≤10000输入样例
6 4 1 7 3 2 5 6 1 2 4 1 3 5 2 4 1 3 5 2 3 6 1 2 5 4 6 6 4 5 6
输出样例
35 16 26 13
样例解释
对于第一条路线,小 R 会经过 2→1→3→5
其中在城市 2 处以 7 的价格购买 4 单位粮食,到城市 1 时全部吃完,并用 1 的价格购买 7 单位粮食,然后到达终点。