建一个10个空间的数组,代表十个房间,0代表没人,1代表有人。
L就从左找第一个为0的房间,赋1;R就从右找第一个为0的房间,赋1;数字就把那个房间清空。
复杂度O(10N)最多1e6。
注意房间从0开始,写循环<=0后者>=0!
else只与最近的if匹配!!!!不想匹配记得加括号!!!
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <string>
using namespace std;
int r[15];
string s;
int main()
{
int n;
cin>>n;
cin>>s;
for(int j=0;j<n;j++)
{
if(s[j]=='L')
{
for(int i=0;i<10;i++)
if(r[i]==0)
{
r[i]=1;
break;
}
}
else if(s[j]=='R')
{
for(int i=9;i>=0;i--)//这里是>=0不是>0!!!
if(r[i]==0)
{
r[i]=1;
break;
}
}
else r[s[j]-'0']=0;
}
for(int i=0;i<10;i++)
cout<<r[i];
}//else只与最近的if匹配
跳柱子问题,从上一个到下一个最多跳k高度,可以从柱子上拿砖或放砖。
把背包所有砖放在当前柱子,和下一个柱子做差,h[i+1]-(m+h[i])<k 代表可以翻过去;设每次翻越m会得到n块,h[i+1]-(h[i]-n)=k,无论n正负都是成立的,n为负时代表最少放柱子上n块,n为正时代表最多拿n块。n=k-h[i+1]+h[i],即每一次翻越后,m+=k-h[i+1]+h[i],但是一次最多拿h[i]块,每一次m+=min(h[i],k-h[i+1]+h[i])。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;
int h[110];
int main()
{
int t,n,m,k;
cin>>t;
while(t--)
{
bool flag=1;
cin>>n>>m>>k;
for(int i=1;i<=n;i++)
cin>>h[i];
for(int i=1;i<n;i++)
{
if(h[i+1]-h[i]-m>k)
{
flag=0;
break;
}
else
{
if(k-h[i+1]+h[i]<h[i])
m+=k-h[i+1]+h[i];
else
m+=h[i];
}
}
if(flag)
cout<<"YES"<<endl;
else
cout<<"NO"<<endl;
}
}
题意是里面一个内圆,一个外圆,内圆被等角度的n个均匀分布的墙分成n块,外圆被m个均匀分布的墙分成m块,问你从某一块能不能到另一块。
在某一角度,如果内圆于外圆在此角度都有墙,那这个角度将被锁死是不能通过的。这种死墙的个数就是n,m的公因数。看图就很容易看出来。死墙将圆分成gcd(n,m)块,起点和终点不在一个块就无法到达。判断:
外墙第i块在第
(i-1)/(m/g)
内墙第j块就是
(j-1)/(n/g)
注意是(i-1)
从0开始计数的分块不用-1,从1开始的都需要
记得开long long
一开始还以为一定是起点终点一个内一个外,审题!!!!!!!!!看完题看一下样例!!!!!
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;
typedef long long LL;
LL gcd(LL a,LL b)
{
if(b==0)
return a;
if(b>a)
return gcd(b,a) ;
return gcd(b,a%b);
}
int main()
{
LL n,m,sy,ey;
LL q,ex,sx;
cin>>n>>m>>q;
while(q--)
{
cin>>sx>>sy>>ex>>ey;
LL g=gcd(n,m),a,b;//这里当时忘写longlong了,醉了
if(sx==1)
a=(sy-1)/(n/g);
else
a=(sy-1)/(m/g);
if(ex==1)
b=(ey-1)/(n/g);
else
b=(ey-1)/(m/g);
if(a!=b)
cout<<"NO"<<endl;
else
cout<<"YES"<<endl;
}
}
一个n*n的正方形,有白色黑色两种色块,你能消除k*k正方形里的所有黑色,问一次操作后,全是白色的行和列之和的最大值。
分成行列两种情形分别计算。
想将一行的变成白色,就要将所有黑色覆盖掉,因为只能一片的进行覆盖,所以只需要考虑这行第一个黑块和最后一个黑块,只要它们俩被覆盖掉,那么这行就会变成全白,假设第一个位置是l,最后一个是r,先赋予初值-1。新建一个n*n方格,ans[i][j]表示当k*k左上角在(i,j)位置时,全白行和全白列的数量。不包括一开始就全白的。
以行的情况举例:
1、第i行没有黑块,r=l=-1,那么用anss来存储,anss++,意味着无论放哪里答案都有这一行
2、r-l+1<=k意味着这一行可以被覆盖,那么能覆盖的k*k方块左上角的格子ans[ii][jj]++;ii的范围是[i-k+1,i],设dis=r-l+1,jj的范围是[l+dis-k,l]。都是闭区间。
3.r-l+1>k那么放哪里这一行都不会全白,直接下一行。
列的情况相同。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;
char sq[2010][2010];
int ans[2010][2010];
int main()
{
int n,k,f=0,anss=0;
cin>>n>>k;
for(int i=0;i<n;i++)
cin>>sq[i];
for(int i=0;i<n;i++)
{
int l=-1,r=-1,f=0;
for(int j=0;j<n;j++)
{
if(sq[i][j]=='B')
if(l==-1)
l=j,r=j;
else
{
r=j;
if(r-l+1>k)
{
f=1;
break;
}
}
}
if(l==-1)
{
anss++;
continue;
}
if(f==1)
continue;
int dis=r-l+1;
for(int ii=0;ii<=k-1;ii++)
{
if(i-ii<0) break;
for(int jj=0;jj<=k-dis;jj++)
{
if(l-jj<0) break;
ans[i-ii][l-jj]++;
}
}
}
for(int i=0;i<n;i++)
{
int l=-1,r=-1,f=0;
for(int j=0;j<n;j++)
{
if(sq[j][i]=='B')
if(l==-1)
l=j,r=j;
else
{
r=j;
if(r-l+1>k)
{
f=1;
break;
}
}
}
if(l==-1)
{
anss++;
continue;
}
if(f==1)
continue;
int dis=r-l+1;
for(int ii=0;ii<=k-dis;ii++)
{
if(l-ii<0) break;
for(int jj=0;jj<=k-1;jj++)
{
if(i-jj<0) break;
ans[l-ii][i-jj]++;
}
}
}
int maxn=0;
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
maxn=max(maxn,ans[i][j]);
cout<<maxn+anss;
}