目录
1839:【05NOIP提高组】谁拿了最多奖学金(用例只通过30%)
搜索与回溯
1222:放苹果
【题目描述】
把M�个同样的苹果放在N�个同样的盘子里,允许有的盘子空着不放,问共有多少种不同的分法?(用K�表示)
5,1,1
和1,5,1
是同一种分法。【输入】
第一行是测试数据的数目t�(0≤t≤200≤�≤20)。以下每行均包含二个整数M�和N�,以空格分开。1≤M,N≤101≤�,�≤10。
【输出】
对输入的每组数据M�和N�,用一行输出相应的K。
【输入样例】
1 7 3
【输出样例】
8
#include<iostream>
using namespace std;
const int N = 1e5 + 10;
int t, n, m;
int cnt[N];
int ans = 0;
//搜索状态为s, s代表当前已经搜索的答案的累加和
void dfs(int s, int depth) {
//5.终止条件
if (s > n) return;
if (depth <= m + 1 && s == n) {//n选r问题更改条件处
ans++;
return;
}
//1.枚举方案(枚举的时候直接排列变组合)
for (int i = cnt[depth - 1]; i <= n; i++) {
//2.本题需要重复搜索,则不需要加标记,故第二步略
//3.搜索
cnt[depth] = i;
dfs(s + i, depth + 1);
//4.回溯,若s作为状态传入dfs,则回溯的时候,s自动还原
}
}
int main() {
cin >> t;
while (t--) {
cin >> n >> m;
cnt[0] = 1;
ans = 0;//多组数据,相关状态初始化
dfs(0, 1);//初始状态
cout << ans << endl;
}
return 0;
}
1221:分成互质组
【题目描述】
给定n个正整数,将它们分组,使得每组中任意两个数互质。至少要分成多少个组?
【输入】
第一行是一个正整数n。1 ≤ n ≤ 10。
第二行是n个不大于10000的正整数。
【输出】
一个正整数,即最少需要的组数。
【输入样例】
6 14 20 33 117 143 175
【输出样例】
3
本题需掌握的知识点:
1.互质的两个数a,b满足gcd(a,b)=1
2.若a,b,c互质,则c与a*b互质,反之也成立
#include<iostream>
using namespace std;
const int N = 1e4 + 10;
int n, a[N];
int gcd(int a, int b) {
return b == 0 ? a : gcd(b, a % b);
}
int main() {
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> a[i];
}
for (int i = 1; i <= n; i++) {//清零的位置不需要考虑
for (int j = i + 1; j <= n; j++) {
if (a[i] != 0 && gcd(a[i], a[j]) == 1) {
a[i] *= a[j];
a[j] = 0;
}
}
}
int cnt = 0;
for (int i = 1; i <= n; i++) if (a[i] != 0) cnt++;
cout << cnt << endl;
return 0;
}
1218:取石子游戏
【题目描述】
有两堆石子,两个人轮流去取。每次取的时候,只能从较多的那堆石子里取,并且取的数目必须是较少的那堆石子数目的整数倍,最后谁能够把一堆石子取空谁就算赢。
比如初始的时候两堆石子的数目是25和7。
25 7 --> 11 7 --> 4 7 --> 4 3 --> 1 3 --> 1 0 选手1取 选手2取 选手1取 选手2取 选手1取 最后选手1(先取的)获胜,在取的过程中选手2都只有唯一的一种取法。
给定初始时石子的数目,如果两个人都采取最优策略,请问先手能否获胜。
【输入】
输入包含多数数据。每组数据一行,包含两个正整数a和b,表示初始时石子的数目。
输入以两个0表示结束。
【输出】
如果先手胜,输出"win",否则输出"lose"。
【输入样例】
34 12 15 24 0 0
【输出样例】
win lose
【提示】
假设石子数目为(a,b)且a >= b,如果[a/b] >= 2则先手必胜,如果[a/b]<2,那么先手只有唯一的一种取法。[a/b]表示a除以b取整后的值。
#include<iostream>
using namespace std;
//搜索状态为a,b代表两堆石子的数量
bool dfs(int a, int b) {
if (a < b) swap(a, b);
if (a % b == 0) return true;//某一方赢了
//枚举b的倍数i,但是要保证i*b不超过a
for (int i = a / b; i >= 1; i--)
//枚举所有取法,但凡能找到一种让对方输的情况,那么当前选手都会赢
if (dfs(a - i * b, b) == false) return true;
return false;//枚举所有取法,都没找到一种让对方输的情况,那么当前选手输
}
//选手1执行dfs(7,3)=true dfs(1,3)=true dfs(4,3)=false
//选手2执行dfs(4,3)=false dfs(1,3)=true
//选手1执行dfs(1,3)赢了
//选手2执行dfs(1,3)赢了
int main() {
int a, b;
while (cin >> a >> b && a && b) {
if (dfs(a, b) == true) cout << "win" << endl;
else cout << "lose" << endl;
}
return 0;
}
数组
1126:矩阵转置
#include<iostream>
using namespace std;
const int N = 1e2 + 10;
int a[N][N];
int main()
{
int n, m;
cin >> n >> m;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
cin >> a[i][j];
for (int i = 1; i <= m; i++)
{
for (int j = 1; j <= n; j++)
cout << a[j][i] << " ";
cout << endl;
}
return 0;
}
1127:图像旋转 |
#include<iostream>
using namespace std;
const int N = 1e2 + 10;
int a[N][N];
int n, m;
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 = 1; j <= m; ++j)//遍历矩阵b,m行n列
{
for (int i = n; i >= 1; --i)
cout << a[i][j] << ' ';
cout << endl;
}
return 0;
}
1128:图像模糊处理
#include<iostream>
#include<cmath>
using namespace std;
const int N = 1e2 + 10;
int a[N][N],b[N][N];
int n, m;
int s;//上下左右以及该点的平均值
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 i = 1; i <= n; ++i)
{
for (int j = 1; j <= m; ++j)
{
if (!(i == 1 || i == n || j == 1 || j == m))
{
s = a[i][j] + a[i - 1][j] + a[i + 1][j] + a[i][j - 1] + a[i][j + 1];
s = round((double)s / 5);
b[i][j] = s;
}
else
b[i][j] = a[i][j];
}
}
for (int i = 1; i <= n; ++i)
{
for (int j = 1; j <= m; ++j)
cout << b[i][j] << " ";
cout << endl;
}
return 0;
}
1120:同行列对角线的格
#include<iostream>
#include<cmath>
using namespace std;
const int N = 1e2 + 10;
int a[N][N],b[N][N];
int n, x,y;
int main()
{
cin >> n >> x>>y;
for (int j = 1; j <= n; ++j)
printf("(%d,%d) ", x, j);
putchar('\n');
for (int i = 1; i <= n; ++i)
printf("(%d,%d) ", i, y);
putchar('\n');
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= n; ++j)
if (i - j == x - y)
printf("(%d,%d) ", i, j);
putchar('\n');
for (int i = n; i >= 1; --i)
for (int j = 1; j <= n; ++j)
if (i + j == x + y)
printf("(%d,%d) ", i, j);
putchar('\n');
return 0;
}
string
2046:【例5.15】替换字母
#include<iostream>
#include<string>
using namespace std;
string s;
char a, b;
int main()
{
getline(cin, s);
cin >>a>>b;
for (auto &c : s)
if (c == a)
c =b;
cout << s;
return 0;
}
2047:【例5.16】过滤空格
#include<iostream>
#include<string>
using namespace std;
string s;
char a, b;
int main()
{
getline(cin, s);
cin >>a>>b;
for (auto &c : s)
if (c == a)
c =b;
cout << s;
return 0;
}
2047:【例5.16】过滤空格
#include<iostream>
#include<string>
using namespace std;
string s;
int main()
{
while(cin>>s)
cout << s<<" ";
return 0;
}
2048:【例5.18】串排序
string版本
#include<iostream>
#include<string>
#include<map>
#include<algorithm>
using namespace std;
string s;
int main()
{
int n; cin >> n;
string s[25];
for (int i = 1; i <= n; i++)
{
cin >> s[i];
}
sort(s + 1, s + 1 + n);
for (int i = 1; i <= n;i++) {
cout << s[i] << endl;
}
return 0;
}
map版本
#include<iostream>
#include<string>
#include<map>
using namespace std;
string s;
int main()
{
map<string, int>mp;
int n; cin >> n;
for (int i = 1; i <= n; i++)
{
cin >> s;
mp.insert({ s,i });
}
for (auto it : mp) {
cout << it.first << endl;
}
return 0;
}
2049:【例5.19】字符串判等
#include<iostream>
#include<string>
#include<map>
#include<algorithm>
using namespace std;
string s;
int main()
{
string s1, s2,ss1,ss2;
getline(cin, s1);
getline(cin, s2);
/*将大写字母全部转换成小写*/
for (auto& c : s1)
if (c >= 'A' && c <= 'Z')
c += 32;
for (auto& c : s2)
if (c >= 'A' && c <= 'Z')
c += 32;
/*将去除空格的字符串复制到新变量*/
for (auto& c : s1)
if (c != ' ')
ss1 += c;
for (auto& c : s2)
if (c != ' ')
ss2 += c;
/*字符串判等*/
if (ss1 == ss2)
cout << "YES";
else
cout << "NO";
return 0;
}
2050:【例5.20】字串包含
#include<iostream>
#include<string>
#include<map>
#include<algorithm>
using namespace std;
int main()
{
string s1, s2;
cin >> s1 >> s2;
/*判断s1和s2谁的长度长*/
if (s1.length() < s2.length())
swap(s1, s2);
s1 += s1;
if (s1.find(s2) != -1)
cout << "true";
else
cout << "false";
return 0;
}
1839:【05NOIP提高组】谁拿了最多奖学金(用例只通过30%)
#include<iostream>
#include<string>
#include<map>
#include<algorithm>
using namespace std;
const int N = 1e2 + 10;
struct stu {
string name;
int qmscore;
int bjscore;
char gb;
char sf;
int lw;
int sum;
} s[N];
bool cmp(stu a, stu b) {
if (a.sum == b.sum)
return false;
else
return a.sum > b.sum;
}
int main() {
int n;
cin >> n;
for(int i=0; i < n; i++) {
cin >> s[i].name >> s[i].qmscore >> s[i].bjscore >> s[i].gb >> s[i].sf >> s[i].lw;
s[i].sum = 0;
if (s[i].qmscore > 80 && s[i].lw >= 1) s[i].sum += 8000;
if (s[i].qmscore > 85 && s[i].bjscore > 80) s[i].sum += 4000;
if (s[i].qmscore > 90) s[i].sum += 2000;
if (s[i].qmscore > 85 && s[i].sf == 'Y') s[i].sum += 1000;
if (s[i].qmscore > 80 && s[i].gb == 'Y') s[i].sum += 850;
}
sort(s, s + n, cmp);
int total_sum = 0;
for (int i = 0; i < n; i++) {
total_sum += s[i].sum;
}
cout << s[0].name << endl << s[0].sum << endl << total_sum;
return 0;
}
1839:【05NOIP提高组】谁拿了最多奖学金
#include<iostream>
#include<string>
#include<map>
#include<algorithm>
using namespace std;
const int N = 1e2 + 10;
string s;
int cnt;//统计数字个数
int main()
{
getline(cin, s);
//c++11特性
for (auto c : s)
if (c >= '0' && c <= '9')
cnt++;
cout << cnt;
return 0;
}