cf gym 102785
Posted yeah17981
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了cf gym 102785相关的知识,希望对你有一定的参考价值。
日常训练系列~
本人在成功的过了三题后完美摸鱼
然后
然后终榜上就真的只过了三题
哭唧唧
a.A lazy controller:签到题,给n组数据,每组数据有a b两个数构成,如果b不是a的倍数,输出“DEFECT
“除此之外,c=b/a,如果n组数据的c全部相同,输出”QUALITY“,否则输出”DEFECT“
真签到好伐,我都不想放代码上来了
b.Gremlins attack:给一个n*n的表格,有m只鬼,k盏明灯,告诉你鬼的位置和这k盏灯的位置,鬼只能在有光的地方走,最开始的时候除了鬼的位置其他都是暗的,这k盏灯依次变亮,问亮到第几盏的时候鬼能逃跑(到达表格边界)
很明显是dfs,每次更新新点,并且在新点的基础上搜索能不能同时到达边界和鬼所在的位置,可以的话输出并跳出
对,就是找个跳出,我他妈找了一天的bug,最后发现是一直输出没有截止
虽然但是找个bfs也不是我写的
#include<iostream>
using namespace std;
int n,m,k,x,y,step=0;
int dark[1000][1000],connect[1000][1000];
int flag=0;
void make(int x,int y)
{
if(x>0)
{
if(connect[x-1][y]==1) connect[x][y]=1;
}
if(x<n-1)
{
if(connect[x+1][y]==1) connect[x][y]=1;
}
if(y>0)
{
if(connect[x][y-1]==1) connect[x][y]=1;
}
if(y<n-1)
{
if(connect[x][y+1]==1) connect[x][y]=1;
}
}
void dfs(int x,int y)
{
if(x>0)
{
if(dark[x-1][y]==1 && connect[x-1][y]==0)
{
connect[x-1][y]=1;
if((x-1==0 || x-1==n-1 )||(y==0 || y==n-1))
{
if(flag!=1)
cout<<step<<endl;
flag=1;
return;
}
dfs(x-1,y);
}
}
if(x<n-1)
{
if(dark[x+1][y]==1 && connect[x+1][y]==0)
{
connect[x+1][y]=1;
if((x+1==0 || x+1==n-1 )||(y==0 || y==n-1))
{
if(flag!=1)
cout<<step<<endl;
flag=1;
return;
}
dfs(x+1,y);
}
}
if(y>0)
{
if(dark[x][y-1]==1 && connect[x][y-1]==0)
{
connect[x][y-1]=1;
if((x==0 || x==n-1 )||(y-1==0 || y-1==n-1))
{
if(flag!=1)
cout<<step<<endl;
flag=1;
return;
}
dfs(x,y-1);
}
}
if(y<n-1)
{
if(dark[x][y+1]==1 && connect[x][y+1]==0)
{
connect[x][y+1]=1;
if((x==0 || x==n-1 )||(y+1==0 || y+1==n-1))
{
if(flag!=1)
cout<<step<<endl;
flag=1;
return;
}
dfs(x,y+1);
}
}
}
int main()
{
//freopen("in.in","r",stdin);//读入数据生成器造出来的数据
//freopen("baoli.txt","w",stdout);
cin>>n>>m>>k;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{
dark[i][j]=0;
connect[i][j]=0;
}
for(int i=1;i<=m;i++)
{
cin>>x>>y;
dark[x][y]=1;connect[x][y]=1;
if((x==0 || x==n-1 )||(y==0 || y==n-1))
{
cout<<step<<endl;
return 0;
}
}
for(int i=1;i<=k;i++)
{
cin>>x>>y;step++;
dark[x][y]=1; make(x,y);
if(connect[x][y]==1)
{
if((x==0 || x==n-1 )||(y==0 || y==n-1))
{
cout<<step<<endl;
return 0;
}
dfs(x,y);
if(flag==1) return 0;
}
}
cout<<"0\\n";
return 0;
}
也可以用并查集将能到达边界的灯和鬼分别放到两个点里(构造),当两个点在一个集中说明此时鬼可以到达边界,输出!
比赛的时候两种方法都写了,并查集爆了,dfs没有标记,喜提wa11
D:dp,在学
E.Hanoi Tower:汉诺塔变形,给一个01串a,a0是顶端的环的状态,an是底端的环的状态,求在汉诺塔的规则下将第一个柱子从1……1到a的最小步数的二进制表达
本题需要在脑海中模拟汉诺塔的步骤,建议配合视频使用 汉诺塔
考虑到一个高度为n的汉诺塔从1到3需要的步数为f[n]=2*f[n-1]+1,用二进制表达就是1……1
又考虑到我们并不需要关心23号柱子上面有几个,所以高度为n的汉诺塔移出只需要f[n-1]+1,即10……0
建一个数组的dp,dp[k]表示用二进制表示步数下第k位的数值
然后从下到上模拟,并记录第i位上面没有处理的部分是在1(flag=0)还是在23(flag=1),将底端的连续的1忽略掉,反正他们也不动。
如果i是0,flag==0,往上记录此时有f个连续的0
如果f==1,将i-1及一上的移到2,i移到3(等同于将高度为i的汉诺塔移出)此时dp[i]++
如果f==0,将i-1及一上的移到2,i移到3写着写着发现好像不用分类,我是傻逼
将高度为i的汉诺塔移出,此时dp[i]++,且上面部分在2的位置
flag==1不用处理,上部分也还在2的位置
如果i为1,此时一定在2的位置,将高度为i的汉诺塔移到1,即为dp[i+1]++且dp[1]--
但是(划重点)让我们来模拟这几个连续1里最后一个1的操作,当它归位时,此时它上面的环应该是摆好了的,因为我们并不需要他们也跟着回去,所以这里要减去 ,即dp[i-t+1]--且dp[1]--,flag=1
想不明白就看视频
最后处理dp,>=2就进位,<0就借位,结束
#include<bits/stdc++.h>
using namespace std;
char z[200];
int dp[200];
int main()
{
int n,f=0,t=0,flag=0;
cin>>n;
cin>>z;
int l=n;
for(int i=n-1;i>=0;i--)
{
if(flag==0&&z[i]=='1')
{
l--;
z[i]-='1';
}
if(z[i]=='0')
{
flag=1;
break;
}
}//这部分没错
bool flag1=0,flag2=0;
int len=l;
for(int i=l-1;i>=0;)
{
while(z[i]=='0'&&i>=0)
{
f++;
i--;
}
if(flag1==0)
{
if(f==1) dp[l-f+1]++;
else dp[l]++;
flag2=1;
}//只移0,不动1
else
{
flag2=1;
}
l=l-f;
f=0;
while(z[i]=='1'&&i>=0)
{
t++;
i--;
}
dp[l+1]++;
dp[l-t+1]--;
flag1=1;
//dp[1]-=2;
l-=t;t=0;
if(l==0)break;
}
flag=1;
for(int i=1;;i++)
{
if(dp[i]==0&&i>len)
{
break;
}
else
{
if(dp[i]!=0)
{
if(dp[i]>=0)
{
dp[i+1]+=dp[i]/2;
dp[i]=dp[i]%2;
flag=i;
}
else
{
if(dp[i]%2==0)
dp[i+1]+=dp[i]/2;
else
dp[i+1]+=dp[i]/2-1;
dp[i]=-dp[i]%2;
flag=i;
}
}
}
}
for(int i=flag;i>=1;i--)
{
cout<<dp[i];
}
}
H.A self-describing sequence:构造,1236无解,45题目给了,其他以0-9为例
0123456789
6210001000
0:n-3
1:2
2:1
n-3:1
结束
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6;
string f;
int main(){
long long n,z,i;
long long k,flag=0;
cin>>n>>k;
if(n==1||n==2||n==3||n==6) flag=1;
else if(n==4)
{
f="1210";
}
else if(n==5)
{
f="21200";
}
if(flag==0) cout<<k<<"\\n";
else
{
cout<<"0\\n";
}
for( i=1;i<=k;i++)
{
cin>>z;
if(flag==0)
{
if(n==4||n==5)
cout<<f[z]<<" ";
else if(z==0)
{
cout<<n-4<<" ";
}
else if(z==1)
{
cout<<2<<" ";
}
else if(z==2)
{
cout<<1<<" ";
}else if(z==n-4)
{
cout<<1<<" ";
}
else
{
cout<<"0 ";
}
}
}
}
j:给两个字符串,串z带*和+且不存在连续的+*,a*代表0-无数个a,a+代表1-无数个a,问zp能否匹配
首先将a+转换成aa*
dp[i][j]表示第i位和j位能否匹配
不想写了,自己看,毁灭吧
#include<bits/stdc++.h>
using namespace std;
const int maxn=2e3+10;
char a[maxn],b[maxn],c[maxn],d[maxn];
int dp[maxn][maxn];
int main(){
cin>>a>>b;
int len1=strlen(a);
int len2=strlen(b);
int k=1;
for(int i=0;i<len1;i++)
{
c[i+k]=a[i];
if(a[i]=='+')
{
c[i+k]=c[i+k-1];
k++;
c[i+k]='*';
}
} //把*换+
len1+=k;
len1--;
for(int i=0;i<len2;i++)
{
d[i+1]=b[i];
}
//cout<<len1<<" "<<len2<<"\\n";
dp[0][0]=1;
for(int i=1;i<=len1;i++)
{
if(c[i]=='*')
{
dp[i][0]=dp[i-2][0];
}
} //可能存在z的前面没有匹配的
for(int i=1;i<=len1;i++)
{
for(int j=1;j<=len2;j++)
{
if(c[i]==d[j])
{
dp[i][j]=dp[i-1][j-1];
//cout<<i<<"x"<<j<<" ";
//cout<<c[i]<<" "<<d[j]<<" "<<dp[i][j]<<"\\n";
}//简单易懂
else
{
if(c[i]=='*')
{
if(dp[i-2][j]==1||dp[i-1][j]==1)//a*转a或空
{
dp[i][j]=1;
//cout<<i<<"b"<<j<<" ";
//cout<<c[i]<<" "<<d[j]<<" "<<dp[i][j]<<"\\n";
}
else if(c[i-1]==d[j]&&(dp[i-1][j-1]==1||dp[i][j-1]==1))
{
dp[i][j]=1;
//cout<<i<<"a"<<j<<" ";
//cout<<c[i-1]<<" "<<d[j]<<" "<<dp[i][j]<<"\\n";
}
}
}
}
}
//cout<<len1<<" "<<len2<<" ";
if(dp[len1][len2]==1){
cout<<"Yes\\n";
}
else
{
cout<<"No\\n";
}
}
over
以上是关于cf gym 102785的主要内容,如果未能解决你的问题,请参考以下文章
cf gym 100960 G. Youngling Tournament set+树状数组