报数问题
问题描述:有n个小朋友围成一圈玩游戏,小朋友从1至n编号,2号小朋友坐在1号小朋友的顺时针方向,3号小朋友坐在2号小朋友的顺时针方向,……,1号小朋友坐在n号小朋友的顺时针方向。
游戏开始,从1号小朋友开始顺时针报数,接下来每个小朋友的报数是上一个小朋友报的数加1。若一个小朋友报的数为k的倍数或其末位数(即数的个位)为k,则该小朋友被淘汰出局,不再参加以后的报数。当游戏中只剩下一个小朋友时,该小朋友获胜。
例如,当n=5, k=2时:
1号小朋友报数1;
2号小朋友报数2淘汰;
3号小朋友报数3;
4号小朋友报数4淘汰;
5号小朋友报数5;
1号小朋友报数6淘汰;
3号小朋友报数7;
5号小朋友报数8淘汰;
3号小朋友获胜。
给定n和k,请问最后获胜的小朋友编号为多少?
输入格式
输入一行,包括两个整数n和k,意义如题目所述。
输出格式
输出一行,包含一个整数,表示获胜的小朋友编号。
样例输入
5 2
样例输出
3
样例输入
7 3
样例输出
4
数据规模和约定
对于所有评测用例,1 ≤ n ≤ 1000,1 ≤ k ≤ 9。
要求:利用单向循环链表存储结构模拟此过程。
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
//建立单向循环链表
typedef struct node{
int data;
struct node *next;
}Linknode,*linklist;
int initlink(linklist &h){
h=new Linknode;
h->data=1;
h->next=h;
return 0;
}
int createlink(linklist &h,int n){
linklist p,q;
p=h;
int i=2;
while(i<=n){
q=new Linknode;
q->data=i;
q->next=h;
p->next=q;
p=p->next;
i++;
}
return 0;
}
int output(linklist &h){
linklist p;
p=h;
while(p->next!=h){
cout<<p->data<<endl;
p=p->next;
}
return 0;
}
int count_off(linklist &h,int n,int k){
int cnt=0,flag=0;
linklist p,q;
p=h;
while(p->next!=h){
p=p->next;
}//找到尾结点
while(p->next!=p){
cnt++;
if(cnt%k==0||cnt%10==k){
q=p->next;
p->next=q->next;
delete q;
}
else{
p=p->next;
}
}
flag=p->data;
return flag;
}
int main(){
int n;//共有n个小朋友
int k;//小朋友报的数为k时进行操作
int ans=0;//获胜小朋友编号
while(cin>>n>>k){
linklist h;
initlink(h);
createlink(h,n);
// output(h);
ans=count_off(h,n,k);
printf("获胜的小朋友编号;");
cout<<ans<<endl;
}
return 0;
}
/*
11 5 correct 8
12 6 correct 10
7 3 correct 4
7 4 correct 7
*/
迷宫问题求解
任务:可以输入一个任意大小的迷宫数据,用非递归的方法求出一条走出迷宫的路径,并将路径输出;
要求:在上交资料中请写明:存储结构、基本算法(可以使用程序流程图)、源程序、测试数据和结果、算法的时间复杂度、另外可以提出算法的改进方法;
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
typedef struct node{
int x;
int y;
}Node;
int n,m;
Node path[1000005];
Node prelocal[1005][1005];
char mapp[1005][1005];
int mov[4][2]={{0,1},{0,-1},{-1,0},{1,0}};
bool flag[1005][1005];
queue<Node>vis;
int inputmap(int m,int n){
for(int i=1;i<=m;i++){
for(int j=1;j<=n;j++){
cin>>mapp[i][j];
}
}
return 0;
}
int bfs(int x,int y,int endx,int endy){
int ans=0;
vis.push({x,y});
while(!vis.empty()){
Node tmp=vis.front();
vis.pop();
ans++;
flag[tmp.x][tmp.y]=1;
if(tmp.x==endx&&tmp.y==endy)return ans;
for(int i=0;i<4;i++){
int nx=tmp.x+mov[i][0];
int ny=tmp.y+mov[i][1];
if(nx>=1&&nx<=m&&ny>=1&&ny<=n&&mapp[nx][ny]=='0'&&flag[nx][ny]==0){
vis.push({nx,ny});
ans++;
flag[nx][ny]=1;
prelocal[nx][ny]={tmp.x,tmp.y};
}
}
}
return 0;
}
int get_map(int x,int y,int bx,int by){
int nx=x,ny=y;
int cnt=0;
while(1){
path[cnt++]={nx,ny};
if(nx==bx&&ny==by)break;
int t1=nx,t2=ny;
nx=prelocal[t1][t2].x;
ny=prelocal[t1][t2].y;
}
return cnt;
}
int main(){
int beginx,beginy,endx,endy;
memset(flag,0,sizeof(flag));
memset(mapp,-1,sizeof(mapp));
while(cin>>m>>n){
inputmap(m,n);
cin>>beginx>>beginy>>endx>>endy;
int ans=bfs(beginx,beginy,endx,endy);
if(ans==0)printf("Sorry! We can't find the way.\n");
else{
int cnt=get_map(endx,endy,beginx,beginy);
for(int i=cnt-1;i>=0;i--){
i!=0?printf("(%d,%d)->",path[i].x,path[i].y):printf("(%d,%d)\n",path[i].x,path[i].y);
}
}
}
return 0;
}
/*
4 5
01100
01110
00001
11011
1 1
4 3
15 15
101111111000110
100111111110010
110111111111111
110000111111111
111110111111111
111110111111111
111110111111111
111110111111111
111110000011111
111111111011111
111111111001111
111100000011111
111101111111111
111100001111111
111111100000111
1 2
15 12
17 50
01111111111111111111111111111111111111111111111111
01111110000000111111111111111111111111111111110111
01111110111101111111111111111111111111111111000000
00000000111101111110000000000111111111111111110111
11111110111101111110111111111111111111111111110111
11111110111101111110111111111111111111111111110111
11111110111101111110111111111111111111111111110111
11111110111101111110000000000000000001111111110111
11111110111101111110111111111111111101111111110111
11111110000000000000111111111111111101111111110111
11111111111111111111111111111111111101111111110111
11111111111111111100000000000000000001100000000111
11111111111111111101111111111111111111101111110111
11111111111111111101111111111111111111101111110111
11111111111111111101111111111111111111101111110000
11111111111111111100000000000000000000001111111011
11111111111111111111111111111111111111111111111011
1 1
17 48
*/
二叉树的构造
任务:已知二叉树的层序和中序遍历序列,或已知二叉树的先序序列、中序序列,试编写算法建立该二叉树( 用递归或非递归的方法都可以)。
要求:能够输入树的各个结点,并能够输出用不同方法遍历的遍历序列;分别建立建立二叉树存储结构的的输入函数、输出层序遍历序列的函数、输出先序遍历序列的函数;
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
typedef struct Benode{
char data;
struct Benode *lchild,*rchild;
}BeNode,*BeTree;
BeTree root;
char pre[1005],mid[1005];
int get_midpos(char s,int l,int r){
for(int i=l;i<=r;i++){
if(mid[i]==s)return i;
}
return -1;
}
//已知先序序列和中序序列
BeTree create(BeTree &t,int pos,int l,int r){
int tmp=get_midpos(pre[pos],l,r);
if(tmp==-1){
t=NULL;
return t;
}
t=new Benode;
t->data=mid[tmp];
create(t->lchild,pos+1,l,tmp-1);
create(t->rchild,pos+tmp-l+1,tmp+1,r);
}
int DLR_output(BeTree &t){//先序
if(t){
cout<<t->data;
DLR_output(t->lchild);
DLR_output(t->rchild);
}
return 0;
}
int LDR_output(BeTree &t){//中序
if(t){
LDR_output(t->lchild);
cout<<t->data;
LDR_output(t->rchild);
}
return 0;
}
int LRD_output(BeTree &t){//后序
if(t){
LRD_output(t->lchild);
LRD_output(t->rchild);
cout<<t->data;
}
return 0;
}
int level_output(BeTree &t){//层序
int front,rear;
Benode *que[1005];
front=rear=0;
if(t){
rear=(rear+1)%1005;
que[rear]=t;
while(rear!=front){
front=(front+1)%1005;
t=que[front];
cout<<t->data;
if(t->lchild){
rear=(rear+1)%1005;
que[rear]=t->lchild;
}
if(t->rchild){
rear=(rear+1)%1005;
que[rear]=t->rchild;
}
}
}
return 0;
}
int output(){
printf("\n先序遍历: ");
DLR_output(root);
printf("\n中序遍历: ");
LDR_output(root);
printf("\n后序遍历: ");
LRD_output(root);
printf("\n层次遍历: ");
level_output(root);
cout<<endl;
}
int main(){
cin>>pre;
cin>>mid;
int len=strlen(pre);
create(root,0,0,len-1);
output();
return 0;
}
/*
ABDEFCHKGJ
DBFEAHKCJG
ABDHECFIJG
HDBEAIFJCG
*/
拓扑排序
任务:编写函数实现图的拓扑排序。
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
#define MAX_VERTEX_NUM 20
typedef int VertexType;
int indegree[MAX_VERTEX_NUM],ans[MAX_VERTEX_NUM];
typedef struct ArcNode{//边结点的类型定义
int adjvex;//边的另一顶点的在数组中的位置
ArcNode *nextarc;//指向下一边结点的指针
}ArcNode;
typedef struct Vnode{//顶点结点及其数组的定义类型
VertexType data;//顶点信息
ArcNode *firstarc;//指向关联该顶点的边链表
}Vnode,AdjList[MAX_VERTEX_NUM];
typedef struct{
AdjList vertices;//顶点结点及其数组
int vexnum,arcnum;//图的当前顶点数和边数
int kind;//图的种类标志
}ALGraph;//图邻接表的类型
void createALGraph(ALGraph &G){
int i,j,k;
ArcNode *s;//定义一个边结点指针
printf("input vexnum and arcnum:");
scanf("%d%d",&G.vexnum,&G.arcnum);
printf("\ninput vertex information:");
for(int k=1;k<=G.vexnum;k++){
scanf("%d",&G.vertices[k].data);
G.vertices[k].firstarc=NULL;
}
printf("\ninput edges:");
for(int k=1;k<=G.arcnum;k++){
scanf("%d%d",&i,&j);
indegree[j]++;
s=new ArcNode;
s->adjvex=j;
s->nextarc=G.vertices[i].firstarc;
G.vertices[i].firstarc=s;
}
}
void FindInDegree(ALGraph &G,int indegree[]){
int t;
ArcNode *p;
for(int k=1;k<=G.vexnum;k++){
indegree[k]=0;//顶点度数初始化(入)
}
for(int k=1;k<=G.vexnum;k++){
p=G.vertices[k].firstarc;
while(p!=NULL){
t=p->adjvex;
indegree[t]++;
p=p->nextarc;
}
}
}
int TopologicalSort(ALGraph G){
int cnt=0;
stack<int>s;
for(int i=1;i<=G.vexnum;i++){
if(indegree[i]==0)
s.push(i);
}
while(!s.empty()){
int x=s.top();
s.pop();
ans[cnt++]=x;
ArcNode *p=G.vertices[x].firstarc;
while(p!=NULL) {
int k=p->adjvex;
indegree[k]--;
if(!indegree[k])
s.push(k);
p=p->nextarc;
}
}
if(cnt<G.vexnum)return 0;
else return 1;
}
int main(){
memset(ans,0,sizeof(ans));
memset(indegree,0,sizeof(indegree));
ALGraph ALG;
createALGraph(ALG);
FindInDegree(ALG,indegree);
int a=TopologicalSort(ALG);
if(a==0)printf("该图不是有向无环图\n");
else{
printf("拓扑排序得到结点序列为:\n");
for(int i=0;i<ALG.vexnum;i++){
i==ALG.vexnum-1?cout<<ans[i]<<endl:cout<<ans[i]<<" ";
}
}
return 0;
}
/*
12 16
1 2 3 4 5 6 7 8 9 10 11 12
1 4 1 2 1 3 1 12 4 5 2 3 3 5 3 7 5 7 3 8 9 12 9 10 10 12 9 11 11 6 6 8
7 9
1 2 3 4 5 6 7
1 2 1 3 2 4 2 5 2 3 4 5 3 6 6 7 7 5
非有向无环图
7 10
1 2 3 4 5 6 7
1 2 1 3 2 4 2 5 2 3 4 5 3 6 6 7 7 5 5 6
*/
散列表的插入、删除和查找
功能要求:
(1)初始化散列表;
(2)向散列表中插入一个元素;
(3)从散列表中删除一个元素;
(4)从散列表中查找一个元素。
散列表通常采用链接法处理冲突,散列文件中每个节点的类型定义为:
Struct FLNode
{ //散列主文件中的节点类型
ElemType data ; //值域
Int next; //指向下一个节点的指针域
};
其中data域用来存储待散列的元素,next域用来存储下一个同义词元素在散列表中的存储位置,即所在节点的位置号。
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
typedef int ElemType;
typedef struct FLnode{
ElemType data;
struct FLnode *next;
}FLNode,*HashTable,**TypeHash;
int mod;
int init(TypeHash &H){
H=new HashTable[mod];
for(int i=0;i<mod;i++){
H[i]=NULL;
}
return 0;
}
int Insert(TypeHash &H,int x){
HashTable insertt;
insertt=new FLNode;
insertt->data=x;
insertt->next=H[x%mod];
H[x%mod]=insertt;
return 0;
}
int Search(TypeHash &H,int x){
HashTable pointer=H[x%mod],t;
int cnt=1,flag=0;
while(pointer!=NULL){
if(pointer->data==x){
flag=1;
break;
}
pointer=pointer->next;
cnt++;
}
if(flag==0)printf("未能找到该元素\n");
else printf("该元素在Hash表中第%d行第%d个\n",x%mod,cnt);
return flag;
}
void Delete(TypeHash &H,int x){
if(!Search(H,x)){
printf("不需要进行删除操作\n");
return;
}
else{
printf("可以进行删除操作\n");
HashTable pointer=H[x%mod],prior;
while(pointer!=NULL){
if(pointer->data==x){
H[x%mod]=pointer->next;
delete pointer;
return;
}
while(pointer!=NULL){
if(pointer->data==x){
prior->next=pointer->next;
HashTable tmp=pointer;
pointer=pointer->next;
delete tmp;
break;
}
}
prior=pointer;
pointer=pointer->next;
}
}
return;
}
void output(TypeHash &H){
for(int i=0;i<mod;i++){
printf("%d:",i);
HashTable pointer=H[i];
while(pointer!=NULL){
cout<<pointer->data<<" ";
pointer=pointer->next;
}
cout<<endl;
}
return;
}
int main(){
TypeHash H;
int x,del,searchh;
cin>>mod;
init(H);//初始化散列表
printf("请输入待存储数据(输入0截止):\n");
while(cin>>x&&x!=0){//待存储数据
Insert(H,x);//插入法将数据存入H中
}
printf("当前散列表:\n");
output(H);
printf("请输入待查找数据(输入0截至):\n");
while(cin>>searchh&&searchh!=0){
Search(H,searchh);
}
printf("请输入待删除数据(输入0截止):\n");
while(cin>>del&&del!=0){
Delete(H,del);
printf("当前Hash表为:\n");
output(H);
}
printf("输出操作后Hash表:\n");
output(H);
return 0;
}
/*
5
19 14 23 1 68 20 84 27 55 11 10 79 0
10 20 0
10 12 0
*/