L-shapes
题目描述
An L-shape is a figure on gridded paper that looks like the first four pictures below. An L-shape contains exactly three shaded cells (denoted by *), which can be rotated in any way.
You are given a rectangular grid. Determine if it contains L-shapes only, where L-shapes can't touch an edge or corner. More formally:
- Each shaded cell in the grid is part of exactly one L-shape, and
- no two L-shapes are adjacent by edge or corner.
For example, the last two grids in the picture above do not satisfy the condition because the two L-shapes touch by corner and edge, respectively.
输入格式
The input consists of multiple test cases. The first line contains an integer t ( 1≤t≤100 ) — the number of test cases. The description of the test cases follows.
The first line of each test case contains two integers n and m ( 1≤n,m≤50 ) — the number of rows and columns in the grid, respectively.
Then n lines follow, each containing m characters. Each of these characters is either '.' or '*' — an empty cell or a shaded cell, respectively.
输出格式
For each test case, output "YES" if the grid is made up of L-shape that don't share edges or corners, and "NO" otherwise.
You can output the answer in any case (for example, the strings "yEs", "yes", "Yes" and "YES" will be recognized as a positive answer).
题意翻译
L形在网格纸上形如下面的前四张图片。L形正好包含三个阴影单元(用*表示),可以以任何方式旋转。
现给你一个矩形网格。确定它是否仅包含L形,其中L形不能接触边或角,也就是说网格中的每个阴影单元正好是一个L形的一部分,并且没有两个L形通过边或角相邻。
例如,上图中的最后两个网格不满足条件,因为两个L形分别通过角和边缘接触。
如果网格满足条件,则输出“YES”,否则输出“NO”。
输入输出样例
输入 #1复制
10 6 10 ........** .**......* ..*..*.... .....**... ...*.....* ..**....** 6 10 ....*...** .**......* ..*..*.... .....**... ...*.....* ..**....** 3 3 ... *** ... 4 4 .*.. **.. ..** ..*. 5 4 .*.. **.. .... ..** ..*. 3 2 .* ** *. 2 3 *.. .** 3 2 .. ** *. 3 3 .** *.* **. 3 3 ..* .** ..*
#include <bits/stdc++.h>
using namespace std;
int a[100][100];
void dfs(int i,int j)
{
if(a[i][j]&&a[i][j+1]&&a[i+1][j])
{
if(!a[i-1][j-1]&&!a[i-1][j]&&!a[i-1][j+1]&&!a[i-1][j+2]&&!a[i][j-1]&&!a[i][j+2]&&!a[i+1][j-1]&&!a[i+1][j+1]&&!a[i+1][j+2]&&!a[i+2][j-1]&&!a[i+2][j]&&!a[i+2][j+1])
{
a[i][j]=a[i][j+1]=a[i+1][j]=0;
return ;
}
}
if(a[i][j]&&a[i][j+1]&&a[i+1][j+1])
{
if(!a[i-1][j-1]&&!a[i-1][j]&&!a[i-1][j+1]&&!a[i-1][j+2]&&!a[i][j-1]&&!a[i][j+2]&&!a[i+1][j-1]&&!a[i+1][j]&&!a[i+1][j+2]&&!a[i+2][j+2]&&!a[i+2][j]&&!a[i+2][j+1])
{
a[i][j]=a[i][j+1]=a[i+1][j+1]=0;
return ;
}
}
if(a[i][j]&&a[i+1][j-1]&&a[i+1][j])
{
if(!a[i-1][j-1]&&!a[i-1][j]&&!a[i-1][j+1]&&!a[i][j-2]&&!a[i][j-1]&&!a[i][j+1]&&!a[i+1][j-2]&&!a[i+1][j+1]&&!a[i+2][j-2]&&!a[i+2][j-1]&&!a[i+2][j]&&!a[i+2][j+1])
{
a[i][j]=a[i+1][j-1]=a[i+1][j]=0;
return ;
}
}
if( a[i][j]&&a[i+1][j+1]&&a[i+1][j])
{
if(!a[i-1][j-1]&&!a[i-1][j]&&!a[i-1][j+1]&&!a[i][j-1]&&!a[i][j+1]&&!a[i][j+2]&&!a[i+1][j-1]&&!a[i+1][j+2]&&!a[i+2][j-1]&&!a[i+2][j]&&!a[i+2][j+1]&&!a[i+2][j+2])
{
a[i][j]=a[i+1][j+1]=a[i+1][j]=0;
return ;
}
}
}
void get_ans()
{
memset(a,0,sizeof(a));
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
char ch;
cin>>ch;
//book[i][j]=ch;
if(ch=='*')
a[i][j]=1;
}
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(a[i][j]==1)
{
dfs(i,j);
}
}
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(a[i][j]==1)
{
cout<<"NO"<<'\n';
return ;
}
}
}
cout<<"YES"<<'\n';
return ;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
get_ans();
}
return 0;
}
P1434 [SHOI2002] 滑雪
题目描述
Michael 喜欢滑雪。这并不奇怪,因为滑雪的确很刺激。可是为了获得速度,滑的区域必须向下倾斜,而且当你滑到坡底,你不得不再次走上坡或者等待升降机来载你。Michael 想知道在一个区域中最长的滑坡。区域由一个二维数组给出。数组的每个数字代表点的高度。下面是一个例子:
1 2 3 4 5
16 17 18 19 6
15 24 25 20 7
14 23 22 21 8
13 12 11 10 9
一个人可以从某个点滑向上下左右相邻四个点之一,当且仅当高度会减小。在上面的例子中,一条可行的滑坡为 24−17−16−124−17−16−1(从 2424 开始,在 11 结束)。当然 2525-2424-2323-……-33-22-11 更长。事实上,这是最长的一条。
输入格式
输入的第一行为表示区域的二维数组的行数 R 和列数 C。下面是 R 行,每行有 C 个数,代表高度(两个数字之间用 11 个空格间隔)。
输出格式
输出区域中最长滑坡的长度。
输入输出样例
输入 #1复制
5 5 1 2 3 4 5 16 17 18 19 6 15 24 25 20 7 14 23 22 21 8 13 12 11 10 9
输出 #1复制
25
说明/提示
对于 100%100% 的数据,1≤R,C≤100。
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
int a[110][110];
int dis[4][2]={0,1,1,0,0,-1,-1,0};
int re[110][110];
int n,m;
int dfs(int x,int y)
{
if(re[x][y])return re[x][y];
re[x][y]=1;
for(int i=0;i<4;i++)
{
int tx,ty;
tx=x+dis[i][0];
ty=y+dis[i][1];
if(tx<1||ty<1||tx>n||ty>m)
continue;
if(a[x][y]>a[tx][ty])
{
re[x][y]=max(dfs(tx,ty)+1,re[x][y]);
}
}
return re[x][y];
}
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
cin>>a[i][j];
}
int ans=0;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
ans=max(ans,dfs(i,j));
}
}
cout <<ans << endl;
return 0;
}
P1496 火烧赤壁
题目背景
曹操平定北方以后,公元 208 年,率领大军南下,进攻刘表。他的人马还没有到荆州,刘表已经病死。他的儿子刘琮听到曹军声势浩大,吓破了胆,先派人求降了。
孙权任命周瑜为都督,拨给他三万水军,叫他同刘备协力抵抗曹操。
隆冬的十一月,天气突然回暖,刮起了东南风。
没想到东吴船队离开北岸大约二里距离,前面十条大船突然同时起火。火借风势,风助火威。十条火船,好比十条火龙一样,闯进曹军水寨。那里的船舰,都挤在一起,又躲不开,很快地都烧起来。一眨眼工夫,已经烧成一片火海。
曹操气急败坏的把你找来,要你钻入火海把连环线上着火的船只的长度统计出来!
题目描述
给定每个起火部分的起点和终点,请你求出燃烧位置的长度之和。
输入格式
第一行一个整数,表示起火的信息条数 n。
接下来 n 行,每行两个整数 a,b,表示一个着火位置的起点和终点(注意:左闭右开)。
输出格式
输出一行一个整数表示答案。
输入输出样例
输入 #1复制
3 -1 1 5 11 2 9
输出 #1复制
11
说明/提示
数据规模与约定
对于全部的测试点,保证1≤n≤2×104,1≤a≤b<231,且答案小于 231231
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
int n;
typedef struct note
{
int x,y;
}Node;
Node a[20010];
bool cmp(Node ii,Node jj)
{
return ii.x<jj.x;
}
int main()
{ cin>>n;
memset(a,0,sizeof(Node));
for(int i=0;i<n;i++)
cin>>a[i].x>>a[i].y;
sort(a,a+n,cmp);
int c[n][2];
int len=0;
c[len][0]=a[0].x;
c[len][1]=a[0].y;
for(int i=1;i<n;i++)
{
if(a[i].x<=c[len][1])
{
if(a[i].y>=c[len][1])
c[len][1]=a[i].y;
}
else
{
c[++len][0]=a[i].x;
c[len][1]=a[i].y;
}
}
// for(int i=0;i<=len;i++)
// cout<<c[i][0]<<' '<<c[i][1]<<endl;
long long sum=0;
for(int i=0;i<=len;i++)
{
sum+=c[i][1]-c[i][0];
}
cout<<sum;
return 0;
}
P1024 [NOIP2001 提高组] 一元三次方程求解
题目描述
有形如:ax3+bx2+cx+d=0 这样的一个一元三次方程。给出该方程中各项的系数(a,b,c,d 均为实数),并约定该方程存在三个不同实根(根的范围在 −100−100 至 100100 之间),且根与根之差的绝对值 ≥1≥1。要求由小到大依次在同一行输出这三个实根(根与根之间留有空格),并精确到小数点后 22 位。
提示:记方程f(x)=0,若存在 22 个数 x1 和 x2,且 x1<x2,f(x1)×f(x2)<0,则在 (x1,x2) 之间一定有一个根。
输入格式
一行,44 个实数 a,b,c,d。
输出格式
一行,33 个实根,从小到大输出,并精确到小数点后 22 位。
输入输出样例
输入 #1复制
1 -5 -4 20
输出 #1复制
-2.00 2.00 5.00
说明/提示
【题目来源】
NOIP 2001 提高组第一题
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
double a,b,c,d;
double f(double x)
{
return a*x*x*x+b*x*x+c*x+d;
}
void find_(double l,double r)
{
while(r-l>0.001)
{
double mid=(l+r)/2.0;
if(f(mid)==0)
{
printf("%.2f ",mid);
return ;
}
else
{
if(f(l)*f(mid)>0)
l=mid;
else
r=mid;
}
}
printf("%.2f ",l);
}
int main()
{
cin>>a>>b>>c>>d;
int ans=0;
for(double i=-100;i<=100&&ans<=3;i++)
{
if(f(i)==0)
{
printf("%.2f ",i);
ans++;
}
else
{
if(f(i)*f(i+1)<0)
{
find_(i,i+1);
ans++;
}
}
}
return 0;
}