csp练题记录(C语言,编译器dev c++)201912-2回收站选址

csp练题记录(C语言,编译器dev c++)201912-2回收站选址

文章目录

  • 一、题目描述
  • 二、思路分析
  • 三、代码
  • 四、反思总结

一、题目描述

csp练题记录(C语言,编译器dev c++)201912-2回收站选址_第1张图片csp练题记录(C语言,编译器dev c++)201912-2回收站选址_第2张图片csp练题记录(C语言,编译器dev c++)201912-2回收站选址_第3张图片csp练题记录(C语言,编译器dev c++)201912-2回收站选址_第4张图片csp练题记录(C语言,编译器dev c++)201912-2回收站选址_第5张图片csp练题记录(C语言,编译器dev c++)201912-2回收站选址_第6张图片csp练题记录(C语言,编译器dev c++)201912-2回收站选址_第7张图片

二、思路分析

解这道题我觉得需要以下两个步骤:1、找出所有的备选地址,用sel[]数组来标识是否是备选地址(在初始代码中);2、对所有备选地址进行评分。
其中,备选地址要具备:它上、下、左,右四邻位都有垃圾;对它评分时,就是看它左上、左下、右上,右下四个对角线元素的有垃圾的个数,分值0~5分。
开始的时候,怎么存储坐标信息让我感觉一筹莫展:想用链表来存储,每一个节点存储了它的上下左右四邻位的信息,这样遍历一遍就可以得到所有的备选地址,但这样带来了一个新的问题:评分时考虑的是它对角线上的,就很麻烦,水平不够,自然是整得越简单越好,于是干脆设置一个二维数组,简单直接。
初始的代码能跑,但很粗糙、暴力:对每一个坐标都完整遍历一遍数组,这样找出它上下左右四邻位共有几处有垃圾,当计数值count为4时,说明它是备选位置。参阅博客和咨询dalao后有了改进思路。
第一次优化思路
邻位的两个元素是相互的,你是我的左,那么相对的,你就是我的右。同理,上下也有一样的性质,也就是说,不必像初始代码中那样每次都完整遍历一遍。因此找备选地址时,就有以下的思路:
(个人感觉有点像递归)遍历到第i个元素时,由于邻位的概念如上是相互的,所以只需找到在它后边和它有邻位关系的,(它和它之前有邻位关系的已经在遍历到之前那个元素时记录过了)。体现在代码中如下:

for(i=0;i<n;i++)
{
  for(j=i+1;j<n;j++)
  {
   if(||||||右侧有垃圾)
   {
    sel[i]++;
    sel[j]++;
   }
  }
}

这样,只要sel[]数组中元素值为4,就说明它是一个备选地址。

三、代码

初始代码:

#include
int main()
{
 int n,i,j;
 long int loc[1000][2]; 
 int sel[1000]={0};
 int score[5]={0},count;
 scanf("%d",&n);
 for(i=0;i<n;i++)//读入坐标 
 {
  scanf("%ld %ld",&loc[i][0],&loc[i][1]);
 }
 //找出备选坐标位置
 for(i=0;i<n;i++)
 {
  count=0;
  for(j=0;j<n;j++)
  {
   if(loc[i][0]==loc[j][0]&&loc[i][1]==loc[j][1]+1//上侧有 
   ||loc[i][0]==loc[j][0]&&loc[i][1]==loc[j][1]-1//下侧有 
   ||loc[i][1]==loc[j][1]&&loc[i][0]==loc[j][0]+1//右侧有 
   ||loc[i][1]==loc[j][1]&&loc[i][0]==loc[j][0]-1)//左侧有 
   {
    count++;
    if(count==4)
    break;
   }
  }
  if(count==4)
  {
   sel[i]=1;
  }
    }
    //评分
 for(i=0;i<n;i++)
 {
  count=0;
  if(sel[i])
  {
   for(j=0;j<n;j++)
   {
    if((loc[i][0]==loc[j][0]+1&&loc[i][1]==loc[j][1]+1)//右上有 
    ||(loc[i][0]==loc[j][0]+1&&loc[i][1]==loc[j][1]-1)//右下有 
    ||(loc[i][0]==loc[j][0]-1&&loc[i][1]==loc[j][1]+1)//左上有 
    ||(loc[i][0]==loc[j][0]-1&&loc[i][1]==loc[j][1]-1))//左下有
    {
     count++;
    } 
   }
   score[count]++;
  }
 } 
 for(i=0;i<5;i++)
 {
  printf("%d\n",score[i]);
 }
 return 0;
}

第一次优化后代码:

#include
int main()
{
 int n,i,j;
 long int loc[1000][2]; 
 bool sel[1000]={0};
 int score[5]={0},count;
 scanf("%d",&n);
 for(i=0;i<n;i++)//读入坐标 
 {
  scanf("%ld %ld",&loc[i][0],&loc[i][1]);
 }
 //找出备选坐标位置
 for(i=0;i<n;i++)
 {
  for(j=i+1;j<n;j++)
  {
   if(loc[i][0]==loc[j][0]&&loc[i][1]==loc[j][1]+1//上侧有 
   ||loc[i][0]==loc[j][0]&&loc[i][1]==loc[j][1]-1//下侧有 
   ||loc[i][1]==loc[j][1]&&loc[i][0]==loc[j][0]+1//右侧有 
   ||loc[i][1]==loc[j][1]&&loc[i][0]==loc[j][0]-1)//左侧有 
   {
    sel[i]++;
    sel[j]++;
   }
  }
    }
    //评分
 for(i=0;i<n;i++)
 {
  count=0;
  if(sel[i]==4)
  {
   for(j=0;j<n;j++)
   {
    if((loc[i][0]==loc[j][0]+1&&loc[i][1]==loc[j][1]+1)//右上有 
    ||(loc[i][0]==loc[j][0]+1&&loc[i][1]==loc[j][1]-1)//右下有 
    ||(loc[i][0]==loc[j][0]-1&&loc[i][1]==loc[j][1]+1)//左上有 
    ||(loc[i][0]==loc[j][0]-1&&loc[i][1]==loc[j][1]-1))//左下有
    {
     count++;
    } 
   }
   score[count]++;
  }
 } 
 for(i=0;i<5;i++)
 {
  printf("%d\n",score[i]);
 }
 return 0;
}

四、反思总结

打代码时,又犯了一个白痴型错误,scanf函数格式马虎了,忘打%,无语了,很慌,之前欠下的学习债不知道能不能还上(。•́︿•̀。)。
不过貌似csp前两题暴力粗糙点能解出来。。。尤其是遇到数据存储拿捏不好用什么数据结构的时候,直接上数组就好了。二维数组可以看作两个一维数组,a[i][j]就可以视为j个a[i]数组(以行序为主?貌似是吧)这在数组使用时是一个容易忽视的点。
在解题过程中,要深挖数据背后隐藏的特性,抓住特性可以拓宽我们的做题思路,同时也可以帮助我们优化代码(◦˙▽˙◦)

你可能感兴趣的:(csp练题记录)