背水一战之C语言

生活不易 请你继续努力

2734,2425,1994,1068,2420,2736,2767,3200,3090 ,3084 ,3085, 3086, 3087 ,3089,~~ ,3097~~
3176,3394,2577,2878, 2607, 2627, (2952C++), 2975C++, 3104 ,1961 ,2969, 1056 ,2970, 2972文件 ,2924文件,2925文件 ,3279,2561,3465,3594,1704,3537
3046,3047,3058,1423,1616,3045,3039,3040,3041,3102,3061,1906,1314,1039 ,1536,3265,1082 ,2413
3235,3345,2414,3122,3332,1712,1701,2281,3166,1318,1743,1783,1759,1773,1720

只需要懂是什么意思就行

2425
指针数组:
#include <stdio.h>
int main()
{ 
   char *p[12]={"January","February","March","April","May","June","July","August","September","October","November","December"};
   int n,i;
   while(scanf("%d",&n)!=EOF)
   {
       if(n<1||n>12)
       printf("Wrong!");
       else
       printf("%s\n",*(p+n-1));
   }
     
}
字符串排序 指针数组方法
#include<stdio.h>
int main()
{
    void sort(char *p[], int n);
    int i;
    char str[10][80];
    char *p[10];
    int n;
    scanf("%d", &n);
    for (i= 0; i < n; i++)
        scanf("%s", str[i]);
    for (i= 0; i<n; i++)
        p[i]= str[i];
    sort(p, n);
    printf("\n");
    for (i= 0; i < n; i++)
        printf("%s\n", p[i]);
    return 0;
}
void sort(char *p[],int n){
	int i,j;
	char * t;
	for(i=0;i<n-1;i++){
		for(j=0;j<n-i-1;j++){
			if(*p[j]>*p[j+1]){
			t=p[j];
			p[j]=p[j+1];
			p[j+1]=t;
		}
		}
	}
}
//3084
//给定一个整数 n,求斐波那契数列前 n 项,部分代码已给出,要求补全题目所缺少的函数。
#include <stdlib.h>
#include <math.h>
#include<stdio.h>
int *solve(int n);

int main()
{
    int n, *p= NULL;
    scanf("%d", &n);
    p= solve(n);
    for (int i= 0; i < n; i++)
        printf(i != n-1 ? "%d " : "%d\n", *(p+i));
    return 0;
}
int *solve(int n){
	int a[10000]={1,1};
	int * p,i;
	if(n==1||n==2){
		//return &1;
		int a=1;
		return &a;
	}
	else for(i=2;i<n;i++){
		 a[i]=a[i-1]+a[i-2];
	}
	return a;
} 
函数参数为指针,这个地方需要注意的是,如果要返回1的指针,必须定义一个变量,赋值为1,然后返回该变量的地址&a。
由于指针没法相加,所以这个地方在函数里面创建一个数组,用来存放斐波那契额数列的后面的元素,然后返回数组名,数组的首地址
3085
函数的名称也是一个地址。想通过指针调用函数,可以定义一个指针变量,等于函数名
int max(int a,int b){
	return a>b?a:b;
	}
int * p;
p=max;//即可通过指针p调用函数max
p(3,5);

3086
malloc函数的创建:
要有强制类型转换,否则指针++会出现不可控性
大小就是malloc里面的。个数×sizeof类型
arr=(int *)malloc(n*sizeof(int));
3087
指针数组和指向数组的指针是不同的。
int *p[4];		//指针数组
int (*p)[4]//指向一维数组的指针
指针数组是数组内存放的虽然定义看着是数据,但实际上存放的是这些数据的地址。输出时也不用用指针乱七八糟的,直接和普通的数组一样就行
3089
calloc函数
void * calloc(n,size);//n:个数,size:每个数的大小
常用格式:
ElemType * p;
p=(ElemType *)calloc(n,size);
3097
用scanf接手结构体里的变量,都用&!!!!!

2607
#include <stdio.h>
#include <stdlib.h>

typedef struct Train
{
    int num;
    struct Train *next;
} Train;

Train *create(int n)
{
    Train *t= (Train*)malloc(sizeof(Train));
    scanf("%d", &(t->num));
    
    if (n == 1)
    {
        t->next= NULL;
    }
    else
    {
        t->next= create(n-1);
    }
    
    return t;
}

void print(Train *p)
{
    if (p != NULL)
    {
        printf("%d ",p->num);
        print(p->next);
    }
    
    return;
}

void del(Train *p)
{
    if (p != NULL)
    {
        Train *t;
        t= p->next;
        free(p);
        del(t);
    }
    
    return;
}

Train *rev(Train *p)
{
    Train *head= NULL, *t;
    
    while(p)
    {
        t= p->next;
        p->next= head;
        head= p;
		p=t; 
    }
    
    return head;
}

int main(void)
{
    int n;
    Train *head;
    Train *rev(Train *p);
    scanf("%d", &n);
    head= create(n);
    head= rev(head);
    print(head);
    del(head);
    return 0;
}
很巧妙。把一个链表一个个倒过来,头变成尾,尾变成头。
Train *rev(Train *p)
{
    Train *head= NULL, *t;
    
    while(p)
    {
        t= p->next;
        p->next= head;
        head= p;
		p=t; 
    }
 ★★★★★
 head是当前的头,永远比p落后落后一个结点。又p->next=head,所以p->next变成了p前面那个,也就是next本来是前面的变成了后面的。所以,这个地方只需要让head到头,p也到头即可。
 
3104
#include <stdio.h>
#include<stdlib.h>
struct Time
{
    int year;int month;int day;int hour;int minute;int second;
};
void getTime(struct Time *pt);
int dayOfYear(struct Time t);
long secondOfyear(struct Time *pt);
int main()
{
    struct Time t;
    int i, n;
    scanf("%d", &n);
    for (i= 0; i < n; i++)
    {
        getTime(&t);
        printf("%d %ld\n", dayOfYear(t), secondOfyear(&t));
    }
    return 0;
}
void getTime(struct Time *pt)
{
    scanf("%d%d%d%d%d%d", &pt->year, &pt->month, &pt->day, &pt->hour, &pt->minute, &pt->second);
    return;
}
int dayOfYear(struct Time t){
		int i,day=0;
		int yue[12]={31,28,31,30,31,30,31,31,30,31,30,31};
		if(t.year%400==0||(t.year%4==0&&t.year%100!=0))
			yue[1]=29;
		for(i=0;i<t.month-1;i++)
			day+=yue[i];
		day+=t.day;
		return day;
}
long secondOfyear(struct Time *pt){
	int yue[12]={31,28,31,30,31,30,31,31,30,31,30,31};
	int i;
	 long long sec=0;
	int day=dayOfYear(*pt);
	sec=day*24*60*60+pt->hour*60*60+pt->minute*60+pt->second;
	return sec;
}
求日期啊,几年的几号啊,用switch不免太过麻烦,定义一个数组十分方便。
要学会运用在一个函数里调用其他函数的返回结果,向上面的就可以直接用datOfYear的返回值直接求今年的第几秒。
1056  2970
带参数的宏变量:
//交换;
#define SWAP(T,m,n) {T s;s=m;m=n;n=s;}
T=int;同样引入第三量来swap。
另:
#define AngleToRadian(degree,minute,second) (((degree+minute/60+second/360))/180)*PI
我认为有要定义一个变量的要用花括号,如果没有只是单纯的计算就用()

1082
★★★★★
Farmer John purchased satellite photos of W×H pixels of his farm (1≤W≤80,1≤H≤1000) and wishes to determine the largest ‘contiguous’ (connected) pasture. Pastures are contiguous when any pair of pixels in a pasture can be connected by traversing adjacent vertical or horizontal pixels that are part of the pasture. (It is easy to create pastures with very strange shapes, even circles that surround other circles.)
Each photo has been digitally enhanced to show pasture area as an asterisk (*) and non-pasture area as a period (.). Here is a 10×5 sample satellite photo:

样例输入

10 5
..*.....**
.**..*****
.*...*....
..****.***
..****.***

样例输出

16
递归不一定是要return
1082
#include<stdio.h>
#include<string.h>
char map[1001][1001];
int n,m,sum,max;
void dfs(int i,int j){
	if((map[i][j]=='.')||i<0||j<0||i>=n||j>=m)
		return;
	else{
		map[i][j]='.';
		sum++;
		dfs(i-1,j);
		dfs(i,j-1);
		dfs(i,j+1);
		dfs(i+1,j);
	}
}
int main(){
	int i,j;
	while(scanf("%d%d",&m,&n)!=EOF){
		if(m==0)
			break;
		max=0;
		for(i=0;i<n;i++)
			scanf("%s",map[i]);
			for(i=0;i<n;i++){
				for(j=0;j<m;j++){
					sum=0;
					if(map[i][j]=='*')
						dfs(i,j);
					if(max<sum) 
						max=sum;
				}
			}
			printf("%d\n",max);
	}
	return 0;
}
//*********************************************
#include<stdio.h>
int main(){
	char a[3][3],i;
	for(i=0;i<3;i++){
	
		scanf("%s",a[i]);
	}	
	for(i=0;i<3;i++){
			printf("%s",a[i]);
		printf("\n");
	}
}
/*对于二维数组,a[i]就是地址,行地址。所以可以直接scanf。
输出的时候,也可以直接输出该行的字符串,也可以一个个输出*/

3146

样例输入

6 9 
....#.
.....#
......
......
......
......
......
#@...#
.#..#.
0 0

样例输出

45
3146 同牧场问题,如出一辙!!
#include<stdio.h>
int sum=0;
	char a[21][21];//注意要把大小+1有'\0'
		int m=1,n=1;
void find(int i,int j){
	if(a[i][j]=='#'||i<0||j<0||i>=n||j>=m)
		return;
	else{
		a[i][j]='#';
		sum++;
		find(i+1,j);
		find(i-1,j);
		find(i,j+1);
		find(i,j-1);
	}
}
int main(){
	int i,j,x,y;//x y代表@所在位置 
	//scanf("%d %d",&m,&n); 
	while(m!=0&&n!=0){
		scanf("%d %d",&m,&n); 
		for(i=0;i<n;i++)
			scanf("%s",a[i]);
	for(i=0;i<n;i++){
		for(j=0;j<m;j++){
			if(a[i][j]=='@'){
				x=i;y=j;
			}
		}
	}
	find(x,y);
	//当在一行中读入的是两个零时,表示输入结束
	printf("%d\n",sum);	
	}
} 

3147
题目描述
在一个给定形状的棋盘(形状可能是不规则的)上面摆放棋子,棋子没有区别。要求摆放时任意的两个棋子不能放在棋盘中的同一行或者同一列,请编程求解对于给定形状和大小的棋盘,摆放 k 个棋子的所有可行的摆放方案 C。

输入
输入含有多组测试数据。

每组数据的第一行是两个正整数 n k,用一个空格隔开,表示了将在一个 n×n 的矩阵内描述棋盘,以及摆放棋子的数目。0<n≤8 0<k≤n
当为 -1 -1 时表示输入结束。

随后的 n 行描述了棋盘的形状:每行有 n 个字符,其中 # 表示棋盘区域,. 表示空白区域(数据保证不出现多余的空白行或者空白列)。

输出
对于每一组数据,给出一行输出,输出摆放的方案数目 C (数据保证 C<231)。

样例输入

2 1
#.
.#
4 4
...#
..#.
.#..
#...
-1 -1

样例输出

2
1
3147 搜索基础之棋盘问题
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int n,k,c,sum;//c来计数即下的第几个棋子,k为棋子的总数,sum表示有多少种摆放方案,n为棋盘的规格//
char a[20][20];//定义一个二维字符型数组//
int b[20];//定义一个标记数组//
void qipan(int x)
{
    int i,j;
    if(c==k)//下的棋子个数正好为棋子总数//
    {
        sum++;//摆放方案+1//
        return ;//退出//
    }
    c++;//若下的棋子个数小于总数,则下的棋子个数+1//
    for(i=x;i<n;i++)//i从当前行x处开始查找,从第x行开始查找,从第x行开始查找!!!!!! 按行查找,一行一行//
    {
        for(j=0;j<n;j++)
        {
            if(a[i][j]=='#'&&b[j]==0)//找出可以放置棋子的位置(并且当前标记数组未标记)//
            {
                b[j]=1;//做上标记//
                qipan(i+1);//在下一行继续寻找注意出口在if(c==k)那里//
                b[j]=0;//标记数组恢复为0//
            }
        }
    }
    c--;//如果为满足if条件,则恢复原数//
}
/*
	也可以把c-- b[j]=0删掉换成:,效果都一样。
	memset(b,0,sizeof(b));
	c=0;
*/
int main()
{
    while(scanf("%d%d",&n,&k)!=EOF)
    {
        int i;
        if(n==-1&&k==-1)
            break;
        c=0;//初始化为0,表示还没下第一个棋子。每重新来时都要初始化,所以在while循环里//
        sum=0;//初始化为0,表示初始方案为0.每重新来时都要初始化,所以在while循环里//
        for(i=0;i<n;i++)
            scanf("%s",&a[i]);//输入棋盘//
        memset(b,0,sizeof(b));//将标记数组全部初始化为0//
        qipan(0);//开始调用,统计方案个数//
        printf("%d\n",sum);
    }
}

关键在于那几个全局变量k,c,标记数组b[20]。k是棋子的总个数,c是当前下的第几个棋子。如果c==k说明正好下完,方案数++。如果没有下完,就开始下下一行。只有这一行的某一列里有#并且该列的标记数组没有标记(标记数组的作用就是甄别列,行是依靠每次的x行都往下移,列就是给每一列设计一个标记数组,如果为1说明这个这一列都被标记了,也就是说这一列都不能在存放了)。每一次从第x行开始查找,意味着x要是递增的,即递归函数里的qipan(i+1)//i代表的就是行。在执行到这里的时候,会去执行递归代码,当最后找到出口的时候,return,然后一层层往外回,这时sum不断++,标记数组b[j]不断复原为0,c不断–,回到最初的。c–与b[j]=0是为了实现多次的输出(while(!=EOF)。 大体就是这样


题目描述
马在中国象棋以日字形规则移动。

请编写一段程序,给定 n×m大小的棋盘,以及马的初始位置 (x,y),要求不能重复经过棋盘上的同一个点,计算马可以有多少途径遍历棋盘上的所有点。

输入
第一行为整数 T (T<10),表示测试数据组数。

每一组测试数据包含一行,为四个整数,分别为棋盘的大小以及初始位置坐标 n,m,x,y。(0≤x<n,0≤y<m,m<10,n<10)

输出
每组测试数据包含一行,为一个整数,表示马能遍历棋盘的途径总数,0 为无法遍历一次

样例输入

1
5 4 0 0

样例输出

32


3149 马走日搜索基础
//马走日奏日 
#include<stdio.h>
#include<string.h>
int dx[]={0,1,1,-1,-1,2,2,-2,-2};
int dy[]={0,2,-2,2,-2,-1,1,1,-1};
int a[111][111];
int n,t,m,x,y,step,sum;		//step是一共走了多少步,棋盘的规格是n*m,x y 是马的初始位置,t是输入几组 
int dfs(int x,int y,int step){
	int l;
	if(step>=m*n){			//如果一共走的步数>棋盘上所有的点个数,说明已经走完,方案加1 
		sum++;
		return 0;
	}
	else{
		for(l=1;l<=8;l++){
			int x1=x+dx[l],y1=y+dy[l];//(x1,y1)是下一个马可走的位置,一共有八个(随便画画就能画出来) 
			if(x1<n&&y1<m&&x1>=0&&y1>=0&&a[x1][y1]==0){		//>0 <m <n保证马子还在棋盘内。a[][]=0保证这个点没被走过。 
				a[x1][y1]=1;			//走过之后给个标记 
				dfs(x1,y1,step+1);		//基于现在的x1,y1 再看能不能走,步数要加一因为已经从x,y走到了x1,y1 
				a[x1][y1]=0;			//全部调用完后,return了,最后复原整个棋盘 
			}
		}
	}
}
int main(){
	int i;
	scanf("%d",&t);
	for(i=1;i<=t;i++){
		scanf("%d%d%d%d",&n,&m,&x,&y);
		memset(a,0,sizeof(a));
		a[x][y]=1;
		dfs(x,y,1);
		printf("%d\n",sum);
		memset(a,0,sizeof(a));
		sum=0;
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值