文章目录
1.[P1003 NOIP 2011 提高组] 铺地毯 - 洛谷
算法原理
枚举法:对于一些数据量较小的题目我们可以直接通过枚举出全部的结果,通过结果进行一一对比来判断结果是否正确叫做枚举法
这种方法的优势和劣势非常明显:虽然代码简单但是非常容易超时,后续我们可以通过一些手段进行优化
对于上述这道题我们可以直接通过将所有的数据全部列举到4个数组中,后直接将数组从后向前进行遍历并且一一比较即可
代码实现
#include <iostream>
using namespace std;
const int N = 1e4+10;
int a[N],b[N],c[N],d[N];
int main()
{
int n; cin>>n;
for(int i = 0;i<n;i++)
{
cin>>a[i]>>b[i]>>c[i]>>d[i];
}
int flag = 0;
int x,y; cin>>x>>y;
for(int i = n-1;i>=0;i--)
{
if(x>=a[i]&&x<=a[i]+c[i]&&y>=b[i]&&y<=b[i]+d[i])
{
flag = 1;
cout<<i+1;
break;
}
}
if(flag == 0) cout<<-1;
}
2.[P2010 NOIP 2016 普及组] 回文日期 - 洛谷
算法原理
这道题用一共可以有三种方式:
-
直接进行遍历,后直接比较(这种方式的时间复杂度是最大的)
直接枚举,然后通过条件进行辨别,这里的时间复杂度太高就不进行代码提供了
-
将年份分离开来,通过枚举全部年份来确定回文数(这种时间复杂度较小于上面)
这种方法有以下步骤:
-
枚举年份,通过年份将月份和日用对应关系(
/
和%
)算出,如下:int main() { int x,y; cin>>x>>y; for(int i = 1;i<=9999;i++) { int month = i%10*10 + i/10%10; int day = i/100%10*10 + i/1000; int k = i*10000+month*100+day; } return 0; }
-
有年月后就可以判断这个月的天数,这里可以通过数组和函数实现
static int GetMonthArray[] = {-1,31,28,31,30,31,30,31,31,30,31,30,31}; int GetMonthDay(int year,int month) { if(month==2&&((year%4==0&&year%100!=0)||year%400==0)) return 29; else return GetMonthArray[month]; }
-
-
仅仅枚举月日来确定回文数(这种时间复杂度为三者最小)
和上面的代码相似
代码实现
方法二:
#include <iostream>
using namespace std;
static int GetMonthArray[] = {-1,31,28,31,30,31,30,31,31,30,31,30,31};
int GetMonthDay(int year,int month)
{
if(month==2&&((year%4==0&&year%100!=0)||year%400==0)) return 29;
else return GetMonthArray[month];
}
int main()
{
int x,y; cin>>x>>y;
int ret = 0;
for(int i = 1;i<=9999;i++)
{
int month = i%10*10 + i/10%10;
int day = i/100%10*10 + i/1000;
int k = i*10000+month*100+day;
if((k<=y&&k>=x)&&(month>=1&&month<=12&&day>=1&&day<=GetMonthDay(i,month)))
{
ret++;
}
}
cout<<ret;
return 0;
}
方法三:
#include <iostream>
using namespace std;
static int GetMonthArray[] = {-1,31,29,31,30,31,30,31,31,30,31,30,31};
int main()
{
int x,y; cin>>x>>y;
int cnt = 0;
for(int month = 1;month<=12;month++)
{
for(int day = 1;day<=GetMonthArray[month];day++)
{
int year = day%10*1000 + day/10%100*100 + month%10*10 + month/10%100;
int k = year*10000 + month*100 + day;
if(k>=x&&k<=y) cnt++;
}
}
cout<<cnt;
return 0;
}
3.[P2327 SCOI2005] 扫雷 - 洛谷
算法原理
根据题目我们可以使用两组数组来进行模拟这个题目上的要求:
如上图红色线以内为题目用来模拟扫雷,这时候我们就能发现,如果什么都不做的话是无从下手的,但一旦我们将第一个格子填入0或者是1的话后面的数据就会呈现出下面这样的关系,让我们可以将全部的情况模拟出来:
int check1(int n)
{
a[1] = 0;
for(int i = 2;i<=n+1;i++)
{
a[i] = b[i-1] - a[i-1] - a[i-2];
}
}
这时需要判断的就是:
- 格子不能填入不为1或0的其他数
- 最后一个格子的下一个格子不能填数
满足这两个条件就是一种正确的放雷方式
int check1(int n)
{
a[1] = 0;
for(int i = 2;i<=n+1;i++)
{
a[i] = b[i-1] - a[i-1] - a[i-2];
if(a[i]<0||a[i]>1) return 0;//条件1
}
if(a[n+1]==0) return 1;//条件2
else return 0;
}
代码实现
#include <iostream>
using namespace std;
const int N = 10010;
int a[N],b[N];
int check1(int n)
{
a[1] = 0;
for(int i = 2;i<=n+1;i++)
{
a[i] = b[i-1] - a[i-1] - a[i-2];
if(a[i]<0||a[i]>1) return 0;
}
if(a[n+1]==0) return 1;
else return 0;
}
int check2(int n)
{
a[1] = 1;
for(int i = 2;i<=n+1;i++)
{
a[i] = b[i-1] - a[i-1] - a[i-2];
if(a[i]<0||a[i]>1) return 0;
}
if(a[n+1]==0) return 1;
else return 0;
}
int main()
{
int n; cin>>n;
for(int i = 1;i<=n;i++)
{
cin>>b[i];
}
int ret = 0;
ret += check1(n);
ret += check2(n);
cout<<ret;
}