目录
出现次数最多的数(csp201312-1) :
问题描述
题目简述
给定n个正整数,找出它们中出现次数最多的数。如果这样的数有多个,请输出其中最小的一个。
输入/输出格式
输入格式:
输入的第一行只有一个正整数n(1 ≤ n ≤ 1000),表示数字的个数。
输入的第二行有n个整数s1, s2, …, sn (1 ≤ si ≤ 10000, 1 ≤ i ≤ n)。相邻的数用空格分隔。
输出格式:
输出这n个次数中出现次数最多的数。如果这样的数有多个,输出其中最小的一个。
样例
输入样例:
6
10 1 10 20 30 20
输出样例:
10
问题分析
解题思路
水题,数据只有1-10000,直接开数组存每个数出现的次数,从前向后遍历一遍就可以了。
参考代码
#include <iostream>
#include <cstring>
using namespace std;
int num[10010];
int n;
int main()
{
memset(num,0,sizeof(num));
scanf("%d",&n);
int a;
for(int i=1;i<=n;i++)
{
scanf("%d",&a);
num[a]++;
}
int index=0;
int ans=0;
for(int i=1;i<10010;i++)
{
if(num[i]>ans)
{
index=i;
ans=num[i];
}
}
printf("%d",index);
return 0;
}
心得体会
挺简单的题,没啥可说的,写的时候要注意别数组越界就行了。
ISBN号码(csp201312_2):
问题描述
题目简述
每一本正式出版的图书都有一个ISBN号码与之对应,ISBN码包括9位数字、1位识别码和3位分隔符,其规定格式如“x-xxx-xxxxx-x”,其中符号“-”是分隔符(键盘上的减号),最后一位是识别码,例如0-670-82162-4就是一个标准的ISBN码。ISBN码的首位数字表示书籍的出版语言,例如0代表英语;第一个分隔符“-”之后的三位数字代表出版社,例如670代表维京出版社;第二个分隔之后的五位数字代表该书在出版社的编号;最后一位为识别码。
识别码的计算方法如下:
首位数字乘以1加上次位数字乘以2……以此类推,用所得的结果mod 11,所得的余数即为识别码,如果余数为10,则识别码为大写字母X。例如ISBN号码0-670-82162-4中的识别码4是这样得到的:对067082162这9个数字,从左至右,分别乘以1,2,…,9,再求和,即0×1+6×2+……+2×9=158,然后取158 mod 11的结果4作为识别码。
编写程序判断输入的ISBN号码中识别码是否正确,如果正确,则仅输出“Right”;如果错误,则输出是正确的ISBN号码。
输入/输出格式
输入格式:
输入只有一行,是一个字符序列,表示一本书的ISBN号码(保证输入符合ISBN号码的格式要求)。
输出格式:
输出一行,假如输入的ISBN号码的识别码正确,那么输出“Right”,否则,按照规定的格式,输出正确的ISBN号码(包括分隔符“-”)。
样例
输入样例:
0-670-82162-4
0-670-82162-0
输出样例:
Right
0-670-82162-4
问题分析
解题思路
看着有些麻烦的题,其实挺简单的。本质上是一个字符串处理。但是这个字符串的格式太固定了,因此,我这里直接使用一个辅助数组将字符串中有用的数据的位置标出。这样可以省去遍历字符串的时候跳过”-“。其他的都比较简单,对读出的数字先处理到0-9,之后计算与最后一位相比,然后就是mod的结果为10的情况需要特判。
参考代码
#include <iostream>
#include <cstring>
using namespace std;
char isbn[15];
int pos[11]={-1,1,3,4,5,7,8,9,10,11,13};
char ans;
int main()
{
memset(isbn,32,sizeof(isbn));
scanf("%s",&isbn[1]);
int sum=0;
for(int i=1;i<=9;i++)
{
sum+=i*(isbn[pos[i]]-'0');
}
if((isbn[pos[10]]=='X'&&sum%11==10)||(sum%11==isbn[pos[10]]-'0')) printf("Right");
else
{
if(sum%11==10)
{
ans='X';
}
else
{
ans=sum%11+'0';
}
for(int i=1;i<=12;i++)
{
printf("%c",isbn[i]);
}
printf("%c",ans);
}
return 0;
}
心得体会
比较简单的字符串处理的题目,也不是非常的难。总体来说字符串处理还是比较常出的一类题,还得再练一练。
最大的矩形(csp201312-3):
问题描述
题目简述
在横轴上放了n个相邻的矩形,每个矩形的宽度是1,而第i(1 ≤ i ≤ n)个矩形的高度是hi。这n个矩形构成了一个直方图。请找出能放在给定直方图里面积最大的矩形,它的边要与坐标轴平行。
输入/输出格式
输入格式:
第一行包含一个整数n,即矩形的数量(1 ≤ n ≤ 1000)。
第二行包含n 个整数h1, h2, … , hn,相邻的数之间由空格分隔。(1 ≤ hi ≤ 10000)。hi是第i个矩形的高度。
输出格式:
输出一行,包含一个整数,即给定直方图内的最大矩形的面积。
样例
输入样例:
6
3 1 6 5 2 3
输出样例:
10
问题分析
解题思路
比较裸的一道单调栈的题目。思路就是找到第n个高度向左和向右的最大延伸到的位置。然后两个位置相减乘高度即可算出矩形面积。采用单调非递减栈,从前向后遍历,找到每个高度能延伸到的最右边的位置。从后向前遍历,找到每个高度能延伸到的最左边的位置。求出后遍历一遍,找到最大的面积输出即可。
参考代码
#include <iostream>
#include <stack>
#include <cstring>
using namespace std;
int n;
int height[1010];
int left_pos[1010];
int right_pos[1010];
stack<int> s;
void init()
{
memset(height,0,sizeof(height));
memset(left_pos,0,sizeof(left_pos));
memset(right_pos,0,sizeof(right_pos));
while(!s.empty()) s.pop();
}
void find_right()
{
for(int i=1;i<=n;i++)
{
if(!s.empty())
{
while(!s.empty()&&height[s.top()]>height[i])
{
right_pos[s.top()]=i-1;
s.pop();
}
}
s.push(i);
}
while(!s.empty())
{
right_pos[s.top()]=n;
s.pop();
}
}
void find_left()
{
for(int i=n;i>=1;i--)
{
if(!s.empty())
{
while(!s.empty()&&height[s.top()]>height[i])
{
left_pos[s.top()]=i+1;
s.pop();
}
}
s.push(i);
}
while(!s.empty())
{
left_pos[s.top()]=1;
s.pop();
}
}
int find_max()
{
int ans=-1;
for(int i=1;i<=n;i++)
{
int t=height[i]*(right_pos[i]-left_pos[i]+1);
ans=max(ans,t);
}
return ans;
}
int main()
{
init();
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&height[i]);
}
find_left();
find_right();
printf("%d",find_max());
return 0;
}
心得体会
很久没做单调栈的题目了,感觉用起来有点生疏了。写程序的时候稍微多想了一些时间。但是总体来说还是比较顺利的。
有趣的数(csp201312-4):
问题描述
题目简述
我们把一个数称为有趣的,当且仅当:
1. 它的数字只包含0, 1, 2, 3,且这四个数字都出现过至少一次。
2. 所有的0都出现在所有的1之前,而所有的2都出现在所有的3之前。
3. 最高位数字不为0。
因此,符合我们定义的最小的有趣的数是2013。除此以外,4位的有趣的数还有两个:2031和2301。
请计算恰好有n位的有趣的数的个数。由于答案可能非常大,只需要输出答案除以1000000007的余数。
输入/输出格式
输入格式:
输入只有一行,包括恰好一个正整数n (4 ≤ n ≤ 1000)。
输出格式:
输出只有一行,包括恰好n 位的整数中有趣的数的个数除以1000000007的余数。
样例
输入样例:
4
输出样例:
3
问题分析
解题思路
说实话做的时候完全没有思路,然后上网搜了题解,看了之后才知道是dp。。。首先可以发现,每一个有趣的数的最高位一定是2,这样来说,要产生n位有趣的数,可以通过n-1位递推而来。进而可以发现,要满足有趣的数的排列,有六种状态:1.只有2。2.只有2和0。3.只有2和3。4.只含2,0,1。5,只含2,0,3。6.含0,1,2,3。这六种状态在特定的排列下可以生成有趣的数。具体转移方程如下:
f(i,1)=1
f(i,2)=f(i-1,1)+2f(i-1,2)
f(i,3)=f(i-1,1)+f(i-1,3)
f(i,4)=f(i-1,2)+2f(i-1,4)
f(i,5)=f(i-1,3)+2f(i-1,5)
f(i,6)=f(i-1,4)+f(i-1,5)+2f(i-1,6)
初始状态f(1,1)=1,其他均为0,之后状态转移即可,最后结果在f(n,6)中。
参考代码
#include <iostream>
#include <cstring>
using namespace std;
const int mod=1000000007;
long long num[1010][7];
int n;
int main()
{
scanf("%d",&n);
memset(num,0,sizeof(num));
num[1][1]=1;
for(int i=2;i<=n;i++)
{
num[i][1]=1; //只含2的符合排列的i位数
num[i][2]=(num[i-1][1]+2*num[i-1][2])%mod; //只含0,2的符合排列的i位数
num[i][3]=(num[i-1][1]+num[i-1][3])%mod; //只含2,3的符合排列的i位数
num[i][4]=(num[i-1][2]+2*num[i-1][4])%mod; //只含0,1,2的符合排列的i位数
num[i][5]=(num[i-1][2]+num[i-1][3]+2*num[i-1][5])%mod; //只含0,2,3的符合排列的i位数
num[i][6]=(num[i-1][4]+num[i-1][5]+2*num[i-1][6])%mod; //含0,1,2,3的符合排列的i位数
}
printf("%lld",num[n][6]);
return 0;
}
心得体会
dp还是不太行,很长时间没做加上学的时候也没学的很透彻。以后这方面的题一定要多练。
I’m stuck!(csp201312-5) :
问题描述
题目简述
给定一个R行C列的地图,地图的每一个方格可能是’#’, ‘+’, ‘-’, ‘|’, ‘.’, ‘S’, ‘T’七个字符中的一个,分别表示如下意思:
‘#’: 任何时候玩家都不能移动到此方格;
‘+’: 当玩家到达这一方格后,下一步可以向上下左右四个方向相邻的任意一个非’#‘方格移动一格;
‘-’: 当玩家到达这一方格后,下一步可以向左右两个方向相邻的一个非’#‘方格移动一格;
‘|’: 当玩家到达这一方格后,下一步可以向上下两个方向相邻的一个非’#‘方格移动一格;
‘.’: 当玩家到达这一方格后,下一步只能向下移动一格。如果下面相邻的方格为’#’,则玩家不能再移动;
‘S’: 玩家的初始位置,地图中只会有一个初始位置。玩家到达这一方格后,下一步可以向上下左右四个方向相邻的任意一个非’#‘方格移动一格;
‘T’: 玩家的目标位置,地图中只会有一个目标位置。玩家到达这一方格后,可以选择完成任务,也可以选择不完成任务继续移动。如果继续移动下一步可以向上下左右四个方向相邻的任意一个非’#'方格移动一格。
此外,玩家不能移动出地图。
请找出满足下面两个性质的方格个数:
1. 玩家可以从初始位置移动到此方格;
2. 玩家不可以从此方格移动到目标位置。
输入/输出格式
输入格式:
输入的第一行包括两个整数R 和C,分别表示地图的行和列数。(1 ≤ R, C ≤ 50)。
接下来的R行每行都包含C个字符。它们表示地图的格子。地图上恰好有一个’S’和一个’T’。
输出格式:
如果玩家在初始位置就已经不能到达终点了,就输出“I’m stuck!”(不含双引号)。否则的话,输出满足性质的方格的个数。
样例
输入样例:
5 5
–±+
…|#.
…|##
S-±T
####.
输出样例:
2
问题分析
解题思路
挺好玩的一道bfs的题目。这个题有两个点:第一个是建图。需要将输入的字符矩阵转换成标准的图模型进行存储。第二点就是dfs的思路:首先还是从S开始bfs,求出S的bfs树。此时如果S的bfs树中没有T,那么就输出不存在。如果可以找到T,那么就对S的bfs树中除了S和T的点都运行一遍bfs,如果发现不能找到T,那么这个点就满足要求。最后输出点的数量即可。
参考代码
#include <iostream>
#include <cstring>
#include <vector>
#include <queue>
using namespace std;
class edge
{
public:
int from,to;
edge(){}
edge(int ff,int tt)
{
from=ff;
to=tt;
}
};
vector<int> graph[3000];
vector<edge> edges;
queue<int> q;
char g[55][55];
int r,c;
int start,ed;
int dx[4]={0,0,-1,1};
int dy[4]={-1,1,0,0};
int vis[3000];
int vis2[3000];
void init()
{
for(int i=0;i<3000;i++)
{
graph[i].clear();
}
edges.clear();
memset(g,32,sizeof(g));
}
void addedge(int from,int to)
{
edge e(from,to);
edges.push_back(e);
graph[from].push_back(edges.size()-1);
}
void bfs(int s,int mod)
{
if(mod==0)
{
memset(vis,0,sizeof(vis));
while(!q.empty()) q.pop();
q.push(s);
vis[s]=1;
while(!q.empty())
{
int index=q.front();
q.pop();
for(int i=0;i<graph[index].size();i++)
{
edge& e=edges[graph[index][i]];
if(vis[e.to]==0)
{
vis[e.to]=1;
q.push(e.to);
}
}
}
}
else
{
memset(vis2,0,sizeof(vis2));
while(!q.empty()) q.pop();
q.push(s);
vis2[s]=1;
while(!q.empty())
{
int index=q.front();
q.pop();
for(int i=0;i<graph[index].size();i++)
{
edge& e=edges[graph[index][i]];
if(vis2[e.to]==0)
{
vis2[e.to]=1;
q.push(e.to);
}
if(vis2[ed]==1) return ;
}
}
}
}
int main()
{
init();
scanf("%d %d",&r,&c);
for(int i=1;i<=r;i++)
{
getchar();
for(int j=1;j<=c;j++)
{
scanf("%c",&g[i][j]);
if(g[i][j]=='S') start=(i-1)*c+j;
if(g[i][j]=='T') ed=(i-1)*c+j;
}
}
for(int i=1;i<=r;i++)
{
for(int j=1;j<=c;j++)
{
if(g[i][j]=='+'||g[i][j]=='S'||g[i][j]=='T')
{
for(int k=0;k<4;k++)
{
int xx=i+dx[k];
int yy=j+dy[k];
if(xx>=1&&xx<=r&&yy>=1&&yy<=c&&g[xx][yy]!='#')
{
addedge((i-1)*c+j,(xx-1)*c+yy);
}
}
}
else if(g[i][j]=='-')
{
for(int k=0;k<2;k++)
{
int xx=i+dx[k];
int yy=j+dy[k];
if(xx>=1&&xx<=r&&yy>=1&&yy<=c&&g[xx][yy]!='#')
{
addedge((i-1)*c+j,(xx-1)*c+yy);
}
}
}
else if(g[i][j]=='|')
{
for(int k=2;k<4;k++)
{
int xx=i+dx[k];
int yy=j+dy[k];
if(xx>=1&&xx<=r&&yy>=1&&yy<=c&&g[xx][yy]!='#')
{
addedge((i-1)*c+j,(xx-1)*c+yy);
}
}
}
else if(g[i][j]=='.')
{
int xx=i+dx[3];
int yy=j+dy[3];
if(xx>=1&&xx<=r&&yy>=1&&yy<=c&&g[xx][yy]!='#')
{
addedge((i-1)*c+j,(xx-1)*c+yy);
}
}
}
}
bfs(start,0);
if(vis[ed]==0) printf("I'm stuck!");
else
{
int cnt=0;
for(int i=1;i<=r*c;i++)
{
if(vis[i]==1&&i!=start&&i!=ed)
{
bfs(i,1);
if(vis2[ed]==0)
{
cnt++;
}
}
}
printf("%d",cnt);
}
return 0;
}
心得体会
这几天练图论的题比较多,所以这个题虽然的第五题,但感觉做的还是很顺利的(也可能题比较简单吧),各种模板套上感觉比以前做题时没有章法的乱做要好的多,效率要高的多。总体来说感觉是很不错的。