1. 程式人生 > 其它 >【總結】紀中Day8比賽總結

【總結】紀中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演算法不夠熟練,動態轉移方程沒找出來,克魯斯卡爾演算法不會…..(我太菜了)。

謝謝閱讀

本文來自部落格園,作者:基德不基,轉載請註明原文連結:https://www.cnblogs.com/ssllyw/p/15036660.html