【总结】纪中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