这次Codeforces又悲剧了,做了前面2个题,后面2个题是后面做的。第三个题当时有个细节没有注意到,第四题是想成图论去了,后来才知道原来是DFS。
A题:
其实主要就是求将非0点移动到最中间的位置需要走多少步,这个分别求横坐标和纵坐标与最中间的绝对值差值之和就行了。
#include<cstdio>
#include<cstring>
#include<cstdlib>
#define MAX 6
int main()
{
int a[MAX][MAX],ita,itb;
for(int i=1;i<=5;i++)
for(int j=1;j<=5;j++)
{
scanf("%d",&a[i][j]);
if(a[i][j])
{
ita=i;
itb=j;
}
}
int ans=0;
ans+=abs(ita-3);
ans+=abs(itb-3);
printf("%d\n",ans);
return 0;
}
B题:
题意是说给出一个点a,(a,a)与(0,0)点所构成的一系列正方形,要求求出任意一点包含在k个正方形内,如果找不到则输出-1。
1、显然当k大于n时应该输出-1,当k=n时应该输出(0,0)
2、,当k满足要求的时候,对数组a进行排序后输出(a[k-1],0)或(a[k-1],a[k-1])即可。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define MAX 100
int a[MAX];
int main()
{
int n,k;
while(scanf("%d%d",&n,&k)!=EOF)
{
for(int i=0;i<n;i++)
scanf("%d",&a[i]);
sort(a,a+n);
if(k>n)
printf("-1\n");
else if(k==n)
printf("0 0\n");
else
printf("%d %d\n",a[n-k-1]+1,0);
}
return 0;
}
C题:
这个题题意是给你一系列点的关系,其关系为左右相邻2个区域(eg:给点a b,即b在a的左边第一个或第二个,或在a的右边的第一个或第二个,同理a在应在b左右2个位置内),根据所给出的关系,需要求出该点的正确位置序列,如果得不到这样的序列,那么输出-1。
1、首先应该对每个点计数,在读入数据完成后应该判断每个点是否出现了4次,如果不是,那么输出-1。
2、对于每个点的序列,例如a b c,要想通过a ,b确定c那么需要a的关系点中存在c,并且b的关系点中也同样存在c。因为题目中点从1开始,所以默认以1作为点的起点进行搜索,如果搜索不到,则对应应该输出-1。
代码如下:
#include<cstdio>
#include<cstring>
#define MAX 100001
int count[MAX],vis[MAX],nxt[MAX][5],ans[MAX],flaga,acount,n;
bool has(int now,int k)
{
for(int i=1;i<=nxt[now][0];i++)
if(nxt[now][i]==k)
return true;
return false;
}
void DFS(int pre,int now)
{
if(flaga)
return;
if(acount==n)
{
flaga=1;
return ;
}
for(int i=1;i<=nxt[now][0];i++)
{
if(vis[nxt[now][i]])
continue;
int ita=nxt[now][i];
for(int j=1;j<=nxt[now][0];j++)
{
if(i==j)
continue;
if(acount==1)
{
if(has(ita,nxt[now][j]))
{
ans[acount++]=ita;
vis[ita]=1;
DFS(now,ita);
if(flaga)
break;
acount--;
vis[ita]=0;
break;
}
}
else
{
if(has(pre,ita))
{
ans[acount++]=ita;
vis[ita]=1;
DFS(now,ita);
if(flaga)
break;
acount--;
vis[ita]=0;
break;
}
}
}
}
}
int main()
{
while(scanf("%d",&n)!=EOF)
{
flaga=0;
acount=0;
memset(count,0,sizeof(count));
memset(vis,0,sizeof(vis));
for(int i=0;i<n*2;i++)
{
int ita,itb;
scanf("%d%d",&ita,&itb);
count[ita]++;
count[itb]++;
nxt[ita][++nxt[ita][0]]=itb;
nxt[itb][++nxt[itb][0]]=ita;
}
int flag=0;
for(int i=1;i<=n;i++)
if(count[i]!=4)
{
flag=1;
break;
}
if(flag)
printf("-1\n");
else
{
ans[0]=1;
vis[1]=1;
acount=1;
DFS(0,1);
if(flaga)
{
for(int i=0;i<n-1;i++)
printf("%d ",ans[i]);
printf("%d\n",ans[n-1]);
}
else
printf("-1\n");
}
}
return 0;
}
D题:
题意要求是是求出一个循环回路,其所包含的点数n应该满足n>=k。当时没做出来,后面才知道原来这个题是DFS进行搜索,其实搜索过程也很简单,枚举每一个点作为起点进行搜索,如果搜索到的点与起点想同,并且点数n满足n>=k,那么则得到相应的答案。
代码如下:
#include<cstdio>
#include<cstring>
#include<vector>
#define MAX 100005
using namespace std;
vector<int> w[MAX];
vector<int> ans;
int vis[MAX],n,m,k,getans;
void DFS(int now,int len)
{
if(getans)
return;
ans.push_back(now);
vis[now]=1;
len++;
if(len>=k+1)
for(int i=0;i<w[now].size();i++)
if(w[now][i]==ans[0])
{
getans=1;
return;
}
for(int i=0;i<w[now].size();i++)
if(!vis[w[now][i]])
{
DFS(w[now][i],len);
if(getans)
return;
}
vis[now]=0;
ans.pop_back();
}
int main()
{
while(scanf("%d%d%d",&n,&m,&k)!=EOF)
{
int ita,itb;
getans=0;
memset(vis,0,sizeof(vis));
for(int i=0;i<m;i++)
{
scanf("%d%d",&ita,&itb);
w[ita].push_back(itb);
w[itb].push_back(ita);
}
for(int i=1;i<=n;i++)
{
DFS(i,0);
if(getans)
break;
}
printf("%d\n",ans.size());
for(int i=0;i<ans.size()-1;i++)
printf("%d ",ans[i]);
printf("%d\n",ans[ans.size()-1]);
ans.clear();
}
return 0;
}