12.27总结

P1162 填涂颜色

题目描述

由数字 00 组成的方阵中,有一任意形状闭合圈,闭合圈由数字 11 构成,围圈时只走上下左右 44 个方向。现要求把闭合圈内的所有空间都填写成 22。例如:6\times 66×6 的方阵(n=6n=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
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

输入格式

每组测试数据第一行一个整数 n(1 \le n \le 30)n(1≤n≤30)。

接下来 nn 行,由 00 和 11 组成的 n \times nn×n 的方阵。

方阵内只有一个闭合圈,圈内至少有一个 00。

//感谢黄小U饮品指出本题数据和数据格式不一样. 已修改(输入格式)

输出格式

已经填好数字 2 的完整方阵。

#include<stdio.h>
int n;
int a[35][35];//全局变量会自动初始化
int dx[4]={1,0,0,-1};
int dy[4]={0,1,-1,0};
void dfs(int x,int y)
{
    if(a[x][y]==1)
        return ;
        if(a[x][y]==3)
            return ;
    a[x][y]=3;
    for(int i=0;i<4;i++)
    {
        int nx=x+dx[i],ny=y+dy[i];
        if(0<=nx&&nx<n+2&&0<=ny&&ny<n+2&&a[nx][ny]==0)
            dfs(nx,ny);
    }
}

int main()
{
    int i,j;
    scanf("%d",&n);
    for(i=1;i<=n;i++)
        for(j=1;j<=n;j++)
        scanf("%d",&a[i][j]);//从1开始,在原方阵外围一圈0
        dfs(0,0);
        for(i=1;i<=n;i++)
        {
            for(j=1;j<=n;j++)
            {
                if(a[i][j]==0)
                   printf("2 ");
                    if(a[i][j]==3)
                        printf("0 ");
                        if(a[i][j]==1)
                            printf("1 ");
            }
            printf("\n");
        }
}

在解决该题时碰到了瓶颈处,就是应该怎么找出被1围绕的0或者是在1之外的0。在1之外的0很难找,因为会在边缘处可能被1断开。想了很久,决定从题解中找点思路,发现可以在原方阵的外面围一圈0这样就可以避免找的时候发生中断。此外,还有一个注意的点就是,我根据上一题,进行了8个方位的搜索,

 for(int dx=-1;dx<=1;dx++)
    {
        for(int dy=-1;dy<=1;dy++)
        {
            int nx=x+dx,ny=y+dy;
            if(0<=nx&&nx<N&&0<=ny&&ny<M&&field[nx][ny]==0)
                dfs(nx,ny);
        }

但是这个题目只需要4个方位就可以了。

在函数dfs中还要判断出现a[x][y]=1和a[x][y]=3的情况或者在if语句中加上a[x][y]==0这个条件,避免搜索所有的数。

周老师的区间问题

周老师无聊时乱写了 n 个区间,但处女座的他随后又想将 n 个区间整理合并,但他发现区间太多了,于是他想请你帮帮他

输入

每次测试输入多组数据(小于100组),对于每组输入数据:

第一行为  n ,代表 n 个区间

接下来 n 行,每行两个数 s , t 代表区间 [s,t]

0 < n < 15000

0 <= s <= t < 10000000 

输出

第一行输出一个数字 q ,代表合并后剩余的区间个数

随后 q 行 按从小到大的顺序输出区间

样例输入

3
2 4
1 3
7 7

样例输出

2
1 4
7 7

#include<stdio.h>
void qsort(long long int a[],long long int x,long long int y)
{
   long long int i,j,t,temp;
    if(x>y)
        return ;
    temp=a[x];
    i=x;j=y;
    while(i!=j)
    {
        while(a[j]>=temp&&i<j)
            j--;
        while(a[i]<=temp&&i<j)
            i++;
        if(i<j)
        {
            t=a[i];
            a[i]=a[j];
            a[j]=t;
        }
    }
    a[x]=a[i];
    a[i]=temp;
    qsort(a,x,i-1);
    qsort(a,i+1,y);
    return ;
}//快速排序
int main()
{
    long long int n,left[15000],right[15000],i,j;
    while(~scanf("%lld",&n))
    {
        for(i=0;i<n;i++)
        scanf("%lld %lld",&left[i],&right[i]);
    qsort(left,0,n-1);
    qsort(right,0,n-1);
    j=0;
        for(i=1; i<n; i++)
        {
            if(left[i]<=right[j])
            {
                if(right[j]<=right[i])
                    right[j]=right[i];
                continue;
            }
            else
            {
                j++;
                left[j]=left[i];
                right[j]=right[i];
            }
        }
        printf("%lld\n",j+1);
        for(i=0; i<=j; i++)
            printf("%lld %lld\n",left[i],right[i]);
    }
}

开始我想搞一个大的数组,把出现的区间赋值为0,但是这样组合区间的时候会比较麻烦。所以参照了别人的做法,直接对区间进行整合。我开始用冒泡排序,但是会时间超限,所以最好用快排。然后就是组合区间。如果先比较前一区间的left和后一区间的right判断有没有重合的部分,再判断是部分重合还是全部重合,全部重合就直接进行替换。

P1605 迷宫

题目描述

给定一个 N \times MN×M 方格的迷宫,迷宫里有 TT 处障碍,障碍处不可通过。

在迷宫中移动有上下左右四种方式,每次只能移动一个方格。数据保证起点上没有障碍。

给定起点坐标和终点坐标,每个方格最多经过一次,问有多少种从起点坐标到终点坐标的方案。

输入格式

第一行为三个正整数 N,M,TN,M,T,分别表示迷宫的长宽和障碍总数。

第二行为四个正整数 SX,SY,FX,FYSX,SY,FX,FY,SX,SYSX,SY 代表起点坐标,FX,FYFX,FY 代表终点坐标。

接下来 TT 行,每行两个正整数,表示障碍点的坐标。

输出格式

输出从起点坐标到终点坐标的方案总数。

输入样例

2 2 1
1 1 2 2
1 2

输出样例

1

#include<stdio.h>
int N,M,T,SX,SY,FX,FY,k;
int t[15][2];//记录障碍物坐标
int book[10][10];
int dx[4]={1,0,0,-1};
int dy[4]={0,1,-1,0};
void dfs(int x,int y)
{
    if(x==FX&&y==FY)
    {
        k++;
        return ;
    }//到达终点
    else
    {
        for(int i=0;i<4;i++)
        {
            int nx=x+dx[i],ny=y+dy[i];
            if(nx>0&&nx<=N&&ny>0&&ny<=M&&book[nx][ny]!=1)
            {
              book[nx][ny]=1;
                dfs(nx,ny);
                book[nx][ny]=0;
            }
        }
    }
}
int main()
{
    scanf("%d %d %d",&N,&M,&T);
    scanf("%d %d %d %d",&SX,&SY,&FX,&FY);
    for(int i=0;i<T;i++)
        {
            scanf("%d %d",&t[i][0],&t[i][1]);
            int x=t[i][0],y=t[i][1];
            book[x][y]=1;//把障碍物标记为1
        }
        book[SX][SY]=1;
        dfs(SX,SY);
        printf("%d",k);
}

还是选择搜索来依次找路线,如果找到终点就记录一次。在处理障碍物和走过的路,选择用二维数组book一起记录。在第一次编写出现了小错误,就是对于搜索的那一点我在dfs中给定book[x][y]=1,但是这样会把后续book[nx][ny]搞混。所以就在主函数中设置起点book[SX][SY]=1,方便之后判断下一位置。

题目描述

给定两个整数 n 和 m,要求 m个整数的和为n,m个整数的乘积最大。
满足条件的整数序列可能有多种,请你输出一个字典序最小的满足条件的序列。

输入

第一行输入两个整数 n和m (1 <= n <= 1e9), (1 <= m <= n <= 1e6)。

输出

输出m个用空格隔开的整数表示字典序最小的一种方案数。

#include<stdio.h>
 
int main()
{
    long long int n,m,t,k,i;
    scanf("%lld %lld",&n,&m);
    t=n/m;k=m*(t+1)-n;
    for(i=0;i<m;i++)
    {
        if(i<k)
       printf("%lld ",t);
       else
        printf("%lld ",t+1);
    }
}

开始看到题目,我想要不要用深度优先搜素试一试。但是很麻烦,既要计算乘积,还要判断字典序,所以我去听了关于这个题目的题解,发现就是简单的数学问题,乘积最小即m个数都向平均值靠拢的时候,再把剩余的在平均值后加1即可。

题目描述

阿丢呢离家进,最近胃口不好,吃不下去食堂的饭了,所以决定回家改善伙食。但是呢,阿丢自己做饭很慢很慢的,而很多时候呢下午要上课,没时间回去做饭吃。所以最后决定每3天(就是每隔两天)回去一次,注意每一年的第一天阿丢是要回家的。
比如2012年1月1日阿丢要回家,输出1。2012年1月4日(隔了2天)阿丢又可以回家了,输出2。依次类推。

输入

现在要你输入一个year,一个month,一个day。

输出

输出从你给的这一年的1月1号到你输入的时间点阿丢能回去了几次。输出格式照旧!测试数据多组

#include <stdio.h>
int main()
{
	int year, month, day,n=1;
	while(scanf("%d %d %d", &year, &month, &day)!=EOF)
	{
    int leap, sum,t;
	switch (month)
	{
	case 1:sum = 0;break;
	case 2:sum = 31;break;
	case 3:sum = 59;break;
	case 4:sum = 90;break;
	case 5:sum = 120;break;
	case 6:sum = 151;break;
	case 7:sum = 181;break;
	case 8:sum = 212;break;
	case 9:sum = 243;break;
	case 10:sum = 273;break;
	case 11:sum = 304;break;
	case 12:sum = 334;break;
	default:printf("error\n");
	}
	sum = sum + day;
	if (year%400 == 0 || year%4 == 0 && year%100 != 0)/*判断闰年*/
		leap = 1;
	else
		leap = 0;
	if(leap == 1 && month>2)
		sum = sum+1;
		if(sum<3)
            t=1;
        if(sum%3==0)
            t=sum/3;
        else if(sum%3!=0&&sum>3)
            t=sum/3+1;
		printf("Case #%d:\n%d\n",n,t);
		n++;
	}
	return 0;
}

这个题目就是计算总天数,但是要注意总天数小于3的时候,还有恰好能整除的几种情况。

题目描述

众所周知,实验室的小叶子长的很黑,但是,他自己却总是喜欢颠倒黑白,总喜欢把黑的说成白的(比如 他自己,O(∩_∩)O哈哈~)。这不,有一天,他又开始了他的颠倒之路了。他拿出了两个数,试图颠倒这两个数。规则如下:如果这两个数的反转的和等于两个数和的反转,例如: 12和34。12的反转是21,34的反转是43,21+43=64,而12+34=46,46的反转为64。两个经过反转的数相等,那么他就颠倒失败了,否则他就成功了!!

输入

第一行一个正整数表示测试数据的个数n。
只有n行,每行两个正整数a和b(0<=a,b<=10000)。

输出

如果这两个数的反转的和等于两个数和的反转则输出a+b的值,否则输出小叶子颠倒成功。

#include<stdio.h>
#include<string.h>
#include<math.h>
int fan(char str[])
{
    int l,i,sum=0;
    l=strlen(str);
    for(i=0;i<l;i++)
        sum=sum+(str[i]-48)*pow(10,l-i-1);
    return sum;
}
int main()
{
    int n;
    scanf("%d",&n);
    while(n--)
    {
        int a,b,i;
        scanf("%d %d",&a,&b);
        char str1[10]={'\0'},str2[10]={'\0'},str3[10]={'\0'};
        int x,y,t=a+b,k=t;
        for(i=0;;i++)
        {
            str1[i]=a%10+48;
            a=a/10;
            if(a==0)
                break;
        }
        for(i=0;;i++)
        {
            str2[i]=b%10+48;
            b=b/10;
            if(b==0)
                break;
        }
        for(i=0;;i++)
        {
            str3[i]=t%10+48;
            t=t/10;
            if(t==0)
                break;
        }
        y=fan(str1)+fan(str2);
        x=fan(str3);
        if(x==y)
            printf("%d\n",k);
        else
            printf("小叶子颠倒成功\n");
    }
}

这个题目我选择用字符数组做,这样方便反转。emm好像并没有很方便,但是答案正确。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值