【總結】紀中Day8比賽總結
阿新 • • 發佈:2021-07-20
【總結】紀中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