Codeforces Round #161 (Div. 2)总结

17 篇文章 0 订阅

这次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;
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值