P1162 填涂颜色
题目描述
由数字 0 组成的方阵中,有一任意形状的由数字 11 构成的闭合圈。现要求把闭合圈内的所有空间都填写成 2。例如:6×6 的方阵(n=6),涂色前和涂色后的方阵如下:
如果从某个 0 出发,只向上下左右 4 个方向移动且仅经过其他 0 的情况下,无法到达方阵的边界,就认为这个 0 在闭合圈内。闭合圈不一定是环形的,可以是任意形状,但保证闭合圈内的 0 是连通的(两两之间可以相互到达)。
0 0 0 0 0 0
0 0 0 1 1 1
0 1 1 0 0 1
1 1 0 0 0 1
1 0 0 1 0 1
1 1 1 1 1 1
0 0 0 0 0 0
0 0 0 1 1 1
0 1 1 2 2 1
1 1 2 2 2 1
1 2 2 1 2 1
1 1 1 1 1 1
输入格式
每组测试数据第一行一个整数 n(1≤n≤30)。
接下来 n 行,由 0 和 1 组成的 n×n 的方阵。
方阵内只有一个闭合圈,圈内至少有一个 0。
输出格式
已经填好数字 2 的完整方阵。
输入输出样例
输入 #1复制
6 0 0 0 0 0 0 0 0 1 1 1 1 0 1 1 0 0 1 1 1 0 0 0 1 1 0 0 0 0 1 1 1 1 1 1 1
输出 #1复制
0 0 0 0 0 0 0 0 1 1 1 1 0 1 1 2 2 1 1 1 2 2 2 1 1 2 2 2 2 1 1 1 1 1 1 1
#include <bits/stdc++.h>
using namespace std;
int a[100][100]={};
int b[100][100]={};
int main()
{
int n;
cin>>n;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
cin>>a[i][j];
if(a[i][j]==0){
if(i==1||i==n||j==1||j==n) b[i][j]=3;
}
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(a[i][j]==1){
b[i][j]=1;
continue;
}
if(a[i][j]==0){
if(b[i-1][j]==3||b[i][j-1]==3||b[i][j+1]==3||b[i+1][j]==3) b[i][j]=3;
else b[i][j]=2;
}
}
}
for(int i=n;i>=1;i--){
for(int j=n;j>=1;j--){
if(a[i][j]==0){
if(b[i-1][j]==3||b[i][j-1]==3||b[i][j+1]==3||b[i+1][j]==3) b[i][j]=3;
else b[i][j]=2;
}
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(b[i][j]==3) b[i][j]=0;
cout<<b[i][j]<<" ";
}
cout<<endl;
}
return 0;
}
思路1:主题思路是试图通过几个for循环解决:)
first:将周围所有在边界上(肯定没被1包围)的0赋值为3
second:再用大for循环将3的四方向的0赋值为3,相当于将能走出去与外面的0连接的0赋值
third:但是,要注意,只正向走只能搜到两个方向上的,所以再反向来一次
last:将赋值为3的输出0,其他的输出赋值
思路二:鄙人并没有想出来,但鄙人认为这道题之所以被老师出在bfs档,必定可以用搜索解,所以重点是本人求大佬帮帮我的bfs!!!!!
B3626 跳跃机器人
题目描述
地上有一排格子,共 n 个位置。机器猫站在第一个格子上,需要取第 n 个格子里的东西。
机器猫当然不愿意自己跑过去,所以机器猫从口袋里掏出了一个机器人!这个机器人的行动遵循下面的规则:
- 初始时,机器人位于 1 号格子
- 若机器人目前在 x 格子,那么它可以跳跃到 x−1,x+1,2x 里的一个格子(不允许跳出界)
问机器人最少需要多少次跳跃,才能到达 n 号格子。
输入格式
仅一行,一个正整数,表示 n。
输出格式
仅一行,一个正整数,表示最少跳跃次数。
输入输出样例
输入 #1复制
30
输出 #1复制
6
输入 #2复制
50
输出 #2复制
7
输入 #3复制
64
输出 #3复制
6
输入 #4复制
63
输出 #4复制
8
#include<bits/stdc++.h>
using namespace std;
int a[1000005];
int mark[1000005];
int b[1000005];
int dx[4];
int main(){
memset(mark,0xff,sizeof(mark));
int n;
cin>>n;
int head=1,tail=1;
a[1]=1;b[1]=0;
dx[0]=-1;dx[1]=1;
while(head<=tail){
dx[2]=a[head];
for(int i=0;i<3;i++){
int x=a[head]+dx[i];
if(x>=1){
if(mark[x]==-1){
mark[x]=b[head]+1;
tail++;
a[tail]=x;
b[tail]=mark[x];
if(mark[n]>0){
cout<<mark[n];
return 0;
}
}
}
}
head++;
}
return 0;
}
思路一:主要仿照书上的一道bfs例题
first:在队列数字没有全部出队时,while循环执行以下步骤
second:将三种跳法存在二维数组里,其中2x那种跳法要在每一轮中用得出的x*2标一下
third:遍历三种选择,只要不出界就用将得出的位置加入队列
forth:并用数组存储走到这步的步数,直到第n个数有步数时就输出步数
fifth:将对列队首出队
思路二:对于老师的说法,要尝试用结构体,可我真的不擅长啊!!!有没有大佬能帮帮我ToT
P1808 单词分类
题目描述
Oliver 为了学好英语决定苦背单词,但很快他发现要直接记住杂乱无章的单词非常困难,他决定对单词进行分类。
两个单词可以分为一类当且仅当组成这两个单词的各个字母的数量均相等。
例如 AABAC,它和 CBAAA 就可以归为一类,而和 AAABB 就不是一类。
现在Oliver有 N 个单词,所有单词均由大写字母组成,每个单词的长度不超过 100。你要告诉 Oliver 这些单词会被分成几类。
输入格式
输入文件的第一行为单词个数 N,以下 N 行每行为一个单词。
输出格式
输出文件仅包含一个数,表示这 N 个单词分成的类数。
输入输出样例
输入 #1复制
3 AABAC CBAAA AAABB
输出 #1复制
2
#include<bits/stdc++.h>
using namespace std;
string s[100005];
int num=1;
int main(){
int n;
cin>>n;
for(int i=1;i<=n;i++){
cin>>s[i];
sort(s[i].begin(),s[i].end());
}
sort(s+1,s+1+n);
for(int i=2;i<=n;i++){
if(s[i]!=s[i-1]) num++;
}
cout<<num;
return 0;
}
思路:考虑用排序直接解决
sort(s[i].begin(),s[i].end()) 将二维数组每个单元内数字排序
P1170 兔八哥与猎人
题目描述
兔八哥躲藏在树林旁边的果园里。果园有 M×N 棵树,组成一个 M 行 N 列的矩阵,水平或垂直相邻的两棵树的距离为 1。兔八哥在一棵果树下。
猎人背着猎枪走进了果园,他爬上一棵果树,准备杀死兔八哥。
如果猎人与兔八哥位置的连线上没有其它的果树,猎人就可以看到兔八哥。
现己知猎人和兔八哥的位置,编写程序判断兔子所在的位置是否安全。
输入格式
第一行为 n,表示有 n 组数据,每组数据的第一行为两个正整数 ax 和 ay,表示猎人的位置,第二行为两个正整数 bx 和 by,表示兔八哥的位置。
输出格式
共有 n 行,每行为 yes
或 no
表示兔八哥的位置是否安全。
输入输出样例
输入 #1复制
1 1 1 1 2
输出 #1复制
no
#include<bits/stdc++.h>
using namespace std;
int gcd(int x,int y)
{
if(y==0) return x;
else return (gcd(y,x%y));
}
int main(){
int n,ax,ay,bx,by;
cin>>n;
for(int i=1;i<=n;i++){
cin>>ax>>ay;
cin>>bx>>by;
int d=min(abs(ax-bx),abs(ay-by));
int c=max(abs(ax-bx),abs(ay-by));
if(gcd(d,c)==1) cout<<"no"<<endl;
else cout<<"yes"<<endl;
}
return 0;
}
思路:事实就是,当某提没有思路时,就看一看标签
P1626 象棋比赛
题目描述
有 N 个人要参加国际象棋比赛,该比赛要进行 K 场对弈。每个人最多参加两场对弈,最少参加零场对弈。每个人都有一个与其他人不相同的等级(用一个正整数来表示)。
在对弈中,等级高的人必须用黑色的棋子,等级低的人必须用白色的棋子。每个人最多只能用一次黑色的棋子和一次白色的棋子。为增加比赛的可观度,观众希望 K 场对弈中双方的等级差的总和最小。
比如有 7 个选手,他们的等级分别是30,17,26,41,19,38,18,要进行 3 场比赛。最好的安排是选手 2 对选手 7,选手 7 对选手 5,选手 6 对选手 4。此时等级差的总和等于 (18−17)+(19−18)+(41−38)=5 达到最小。
输入格式
第一行两个正整数 N,K。
接下来有 N 行,第 i 行表示第 i−1 个人等级。
输出格式
在第一行输出最小的等级差的总和。
输入输出样例
输入 #1复制
7 3 30 17 26 41 19 38 18
输出 #1复制
5
#include<bits/stdc++.h>
using namespace std;
int a[100005];
int b[100005];
int main(){
int n;
int k;
int ans=0;
cin>>n>>k;
for(int i=1;i<=n;i++){
cin>>a[i];
}
sort(a+1,a+1+n);
int x=1;
for(int i=2;i<=n;i++){
b[x]=a[i]-a[i-1];
x++;
}
sort(b,b+x);
for(int i=1;i<=k;i++){
ans+=b[i];
}
cout<<ans;
return 0;
}
很简单,自己看吧