【总结】纪中Day8比赛总结

【总结】纪中Day8比赛总结

今天直接挂掉,只有四十分,排七十多名。巨爷kyx300分飞到第八,lhj一如既往稳定在六十七八名。

T1



思路

从题目我们可以看出,它就是让我们求在哪里划几条线才能使交头接耳的人最少。
正解是贪心算法。
首先,我们将会交头接耳的两个人赋值为同一个数。然后我们查找每相邻两行有几对会交头接耳,并记下你现在所在的有交头接耳的人的行数。接着按照数量从大到小排序,取出k个行数后按照序号从小到大输出。
列的做法同上。

Code

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int classroom1[1010][1010],classroom2[1010][1010],answer[1010];
struct h
{
	int numberh,hen;
};
struct s
{
	int numbers,shu;
};
bool cmp(h x,h y)
{
	return x.numberh>y.numberh;
}
bool cmp1(s x,s y)
{
	return x.numbers>y.numbers;
}
int main()
{
	freopen("seat.in","r",stdin);
	freopen("seat.out","w",stdout);
	int m,n,k,l,d,t=0,num=0;
	int x1,y1,x2,y2,maxi=0,maxj=0;
	h a[2010];s b[2010];
	cin>>m>>n>>k>>l>>d;
	for(int i=1;i<=d;i++)
	{
		cin>>x1>>y1;
		cin>>x2>>y2;
		if(y1==y2) classroom1[x1][y1]=classroom1[x2][y2]=i;
		else classroom2[x1][y1]=classroom2[x2][y2]=i;
	}
	for(int i=1;i<m;i++)
	{
		t=0;
		for(int j=1;j<=n;j++)
		{
			if(classroom1[i][j]==0||classroom1[i+1][j]==0) continue;
			if(classroom1[i][j]==classroom1[i+1][j])
			 t++;
		}
		if(t!=0)
		{
			num++;
			a[num].numberh=t;
			a[num].hen=i;
		}
	}//查找有交头接耳的人的行
	sort(a+1,a+num+1,cmp);
	for(int i=1;i<=k;i++)
	 answer[i]=a[i].hen;//取出前k个
	sort(answer+1,answer+k+1);
    for(int i=1;i<=k;i++)
	 cout<<answer[i]<<" ";//按照序号从小到大排序
	memset(answer,0,sizeof(answer)); 
	cout<<endl;
	num=0;
	for(int j=1;j<n;j++)
	{
		t=0;
		for(int i=1;i<=m;i++)
		{
			if(classroom2[i][j]==0||classroom2[i][j+1]==0) continue;
			if(classroom2[i][j]==classroom2[i][j+1])
			 t++;
		}
		if(t!=0)
		{
			num++;
			b[num].numbers=t;
			b[num].shu=j;
			
		}
	}//求列的。
	sort(b+1,b+num+1,cmp1);
	for(int i=1;i<=l;i++)
	 answer[i]=b[i].shu;
	sort(answer+1,answer+l+1);
	for(int i=1;i<=l;i++)
	 cout<<answer[i]<<" ";//
	fclose(stdin);
	fclose(stdout);
	return 0;
}

T2

思路

这道题就是一道DP。
动态转移方程:f[i][j]=f[i-1][j-1]+f[i-1][j+1]

Code

#include<iostream>
#include<cstdio>
using namespace std;
int a[101]={0},b[101]={0},i,j,k,n,m;
int main()
{
	freopen("ball.in","r",stdin);
	freopen("ball.out","w",stdout); 
    cin>>n>>m;
    b[1]=1;
    for(i=1;i<=m;i++)
	{
        for(j=1;j<=n;j++)
		{
            if(i%2==0)
			{
                if(a[j]>0)
		{
                    if(j-1==0) 
			 b[n]+=a[j];
                    else 
			b[j-1]+=a[j];
                    if(j+1==n+1) 
			b[1]+=a[j];
                    else 
			b[j+1]+=a[j];
                }
                if(j==n) 
		for(k=1;k<=n;k++) 
		 a[k]=0;
            }
            else
	    {
                if(b[j]>0)
		{
                    if(j-1==0) 
			a[n]+=b[j];
                    else 
			a[j-1]+=b[j];
                    if(j+1==n+1) 
			a[1]+=b[j];
                    else 
			a[j+1]+=b[j];
                }
                if(j==n) 
		 for(k=1;k<=n;k++) 
		  b[k]=0;
            }
        }
    }
    if(m%2==0) 
	 cout<<b[1];
    else 
     cout<<a[1];
    fclose(stdin);
    fclose(stdout);
    return 0;
}

T3





暂未做出。

T4


思路

最小生成树,解法是克鲁斯卡尔算法。

T5

思路

这道题正解是KMP算法。
但是!我发现可以使用find函数来查找,速度跟KMP差不多。
一个字符一个字符加起来,然后用find来查找是否是数据的前后缀,当你所查找的字符串与数据相同时,直接输出数据的长度并退出。(但这里的老师不让用find函数,不然我就AC了!)

Code

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int main()
{
	int x,y,t=0;
	string a,zc="";
	bool ok;
	cin>>a;
	x=a.size();
	for(int i=0;i<x;i++)
	{
		ok=true;
		zc+=a[i];
		if(zc.size()==a.size())
		{
			cout<<a.size();
			break;
		}
		for(int j=0;j<zc.size();j++)
		{
			if(zc[j]!=a[j])
			{
				ok=false;
				break;
			}
		}
		if(ok==false) continue;
		t=0;
		for(int j=a.size()-1-(zc.size()-1);j<a.size();j++)
		{
			if(zc[t]!=a[j])
			{
				ok=false;
				break;
			}
			t++;
		}
	     if(ok==true)
	      cout<<zc.size()<<" ";
	}
	return 0;
}

总结

如果可以用系统自带函数的话,我的分数应该是120分。
KMP算法不够熟练,动态转移方程没找出来,克鲁斯卡尔算法不会…..(我太菜了)。

谢谢阅读

posted @ 2021-07-20 19:41  基德不基  阅读(31)  评论(0编辑  收藏  举报