安带程序设计与算法课程,期末机考题目
题目平台
3347
思路分析
因为划分集合的规则是,相同元素不能划分到一个集合中,因此一组正整数所划分集合最小的数量,取决于这组整数中重复出现最多的元素的出现个数。
即假如一组整数为1 1 2 2 2 3 3 3 3
,那么这组整数中重复出现次数最多的元素为3
,出现了4
次,那么该组整数最少需要划分为4
个集合。
因为整数大小为2*10e9,因此采用map容器记录数字的出现次数。
代码
#include<bits/stdc++.h>
using namespace std;
int n;
int f()
{
map<int, int> m;
int maxnum=0;
for(int i=0; i<n; i++)
{
int temp;cin >> temp;
m[temp]++;
maxnum = max(maxnum, m[temp]);
}
return maxnum;
}
int main()
{
int t;cin >> t;
while(t--)
{
cin >> n;
cout << f() << endl;
}
}
3348
思路分析
如果把题目中的1/0
序列改为1/-1
序列,那么问题就可以转化为求和最小的子序列,而这个和,就是子序列翻转后,整体增加的正面子的个数res
因此我们在读入数据时需要先保存正面子的个数,即1的个数one_num
最后打印one_num-res
即可
代码
#include<bits/stdc++.h>
using namespace std;
vector<int> m;
int n;
int main()
{
int t; cin>>t;
// cout << "1" << endl;
while(t--)
{
int n;cin >>n;
int a[100010];
int one_num=0;
for(int i=0; i<n; i++)
{
int temp; cin>>temp;
temp = temp?1:-1;
a[i] = temp;
if(temp==1) one_num++;
// cout << "2" << endl;
}
// cout << "one_num:" << one_num << endl;
int res = a[0];
int now = a[0];
for(int i=1; i<n; i++)
{
now = min(now + a[i], a[i]);
res = min(now, res);
// cout << "3" << endl;
// cout << "now:" << now << " res:" << res << endl;
}
cout << one_num-res << endl;
// cout << "4" << endl;
}
}
3349
思路分析
回溯
代码
#include<bits/stdc++.h>
using namespace std;
int m[7][7] = {0};
vector<int> ret;
int dr[4][2]={
{0,1},
{0,-1},
{1,0},
{-1,0}
};
bool boundary(int x, int y)
{
if(x<=5 && x>=1 && y<=5 && y>=1) return true;
else return false;
}
void insert(int n)
{
// 将n插入到ret数组中
// 如果ret数组有n,则不插入
if(count(ret.begin(), ret.end(), n)) return;
else ret.push_back(n);
}
void dfs(int x, int y, int deepth, int num)
{
if(deepth==5)
{
num += pow(10,deepth)*m[x][y];
insert(num);
return;
}
num += pow(10,deepth)*m[x][y];
for(int k=0; k<4; k++)
{
x += dr[k][0];
y += dr[k][1];
if(boundary(x, y)) dfs(x, y, deepth+1, num);
x -= dr[k][0];
y -= dr[k][1];
}
}
int main()
{
for(int i=1; i<=5; i++)
{
for(int j=1; j<=5; j++)
{
cin >> m[i][j];
}
}
for(int x=1; x<=5; x++)
{
for(int y=1; y<=5; y++)
{
dfs(x, y, 0, 0);
}
}
cout << ret.size();
// for(int i=0; i<ret.size(); i++)
// {
// cout << ret[i] << endl;
// }
}
3350
思路分析
这道题不能直接递归去生成字符串,因为数据过大无法保存,并且递归深度太深,会超时
因此这里用的方法是,利用数组len[]
存储从每一个字符串的长度
接下来编写函数void fz(int idx, int m)
,作用是找到第m个字符串中,idx个元素的字符,这个函数就是递归函数,我们是对idx进行递归,因为每一个字符串的构造都是有规律的,那么我们可以分类讨论idx在第m个字符串的中的所处位置:
- 第一种情况:如果
len[m-1] > idx
,说明idx在第m-1个字符串中,我们需要确保idx一定比len[m-1]大,因此这里直接m--
,讨论在第m-1
个字符串下idx的相对位置 - 第二种情况:如果idx位于两个
m-1
字符串的中间的第一个字符,那么就是A - 第三种情况:如果idx位于两个
m-1
字符串中间的其余字符,那么就是u - 第四种情况:如果idx位于第二个
m-1
字符串,那么将进行递归fz(idx-len[m]+len[m-1], m-1)
,这里的意思就是从m-1
个字符串开始计算idx,并从m-1
个字符串进行递归。
代码
// 3350
#include<bits/stdc++.h>
using namespace std;
int n;
int len[100010]={0};
void fz(int idx, int m);
int main()
{
int t;cin >> t;
while(t--)
{
cin >> n;
int i;
for(i=1; ;i++)
{
len[i] = len[i-1]*2 + i + 1;
if(len[i] >= n) break;
}
// cout << i;
fz(n, i);
}
}
void fz(int idx, int m)
{
// 确保在递归中,idx一定是大于len[m-1]的
while(len[m-1] > idx) --m;
if(idx == len[m-1]+1)
{
cout << "A" << endl;
return;
}
else if(idx <= len[m]-len[m-1])
{
cout << "u" << endl;
return;
}
else
{
fz(idx-len[m]+len[m-1], m-1);
return;
}
}