第一次寫博客,有點小小的激動QAQ。表決心,談理想之類的話就很少說了,反正平時說的也夠多了。上大學以後才瞭解到算法競賽究竟是個什麼東西。高一的時候一位清華的教授還來過咱們學校普及了信息學奧賽,當時講了一道例題,上了大學以後才知道,原來,,那是漢諾塔。有點遺憾,在江蘇這樣一個試卷難考生多招生名額少的地方,信息學競賽普及度真的很低。有時候會想,若是我可以有條件在初中甚至小學就接觸編程,如今的我會不會不同。node
上大學以後的我真的變了一我的了吧,或許是高考的失利帶給個人感觸與變化。很多人理解不了,上大學以後的我爲何拼命地學,由於他們不懂,在這裏,我終於能夠不用像之前同樣,全部的努力,全部的能力只被最後的一場考試定義。一位超級優秀的學妹曾經問過我,「學長,你有明確的目標麼」。當時,我啞口無言,才發現原來我只知道埋頭,殊不知道本身要去哪。如今,我終於明白,也終於找到了。python
進入南理工的第一天起,我發誓我要在這裏作到最好,到目前爲止,有不少事情本身作的很不錯,但也有很多事情,本身能清楚感覺到差距的存在,就好比眼前的算法競賽。的確很多比我厲害的人是由於大學之前的基礎,但仍然有許許多多像我同樣從零開始的人啊。全部的不成功,都應該首先從自身努力程度上找緣由吧。記住,你要在這裏作到最好,那就必須讓你的努力配得上你所指望的成就。ios
-----------------------------------------------------------------------手動分割線,進入正題…………^.^c++
前天忽然高燒,養了兩天病。原來在宿舍裏偷偷待一天這麼爽(僅此一次,下不爲例)。程序員
錯過了昨晚的div3,今天下午彙編課上機的時間就用來寫了寫(天天這麼多人找我DEBUG挺煩的其實。)。花了一個小時左右,過了四道題,印象中尚未比這更快過,大概是由於,此次前幾題簡單??粗略估計了一下罰時,若是放在昨晚的話,大概能夠排到800名,錯過了一次絕佳的上分機會(惋惜沒若是~-~)。算法
A題編程
C++數組
1 #include <bits/stdc++.h> 2 using namespace std; 3 #define scan(i) scanf("%d",&i) 4 int a[10]; 5 int main(){ 6 for(int i=1;i<=4;i++){ 7 scan(a[i]); 8 } 9 sort(a+1,a+5); 10 for(int i=1;i<=3;i++){ 11 int x=a[4]-a[i]; 12 printf("%d ",x); 13 } 14 return 0; 15 }
我仍是個病人,先睡覺了。明天再來哈。函數
Python測試
1 a, b, c, d = sorted(map(int, input().split())) 2 print(d-a, d-b, d-c)
只要兩行,有點氣人唉
B題
這道題也很簡單,只要細心一點把全部狀況考慮全就能夠了。對於一組數,能夠對每個數進行三種操做,加一個D,減一個D,或者不變。注意,對於這一組數,正數D的值是固定的。那麼首先須要考慮的是這一組數是由多少個不一樣的值組成,能夠用一下unique函數,(!!!用以前必定要先排序!!上次由於這個問題卡了很久)。若是組成這一組數的值超過三個,那麼必定不存在D知足條件。若是正好是三個,則判斷是否成等差數列。
而對於一個或兩個的狀況,D必定存在,此時須要找一個最小的D。若是是一個,那麼D顯然是0。而,若是是兩個的話,則要分狀況,若是兩數之差爲偶數,則輸出差的一半。而若是兩數之差爲奇數,則只能將其中一個變爲另一個,輸出兩數之差。
C++
1 #include <bits/stdc++.h> 2 using namespace std; 3 int a[105]; 4 #define scan(i) scanf("%d",&i) 5 int main(){ 6 int n;scan(n); 7 for(int i=1;i<=n;i++)scan(a[i]); 8 sort(a+1,a+n+1); 9 int x=unique(a+1,a+n+1)-(a+1); 10 if(x>=4)cout<<-1; 11 else if(x==3){ 12 if((a[2]-a[1])==(a[3]-a[2]))cout<<(a[2]-a[1]); 13 else cout<<-1; 14 } 15 else if(x==2){ 16 if((a[2]+a[1])%2==0)cout<<(a[2]+a[1])/2-a[1]; 17 else cout<<(a[2]-a[1]); 18 } 19 else cout<<0; 20 return 0; 21 }
Python
1 input() 2 a = list(set(list(map(int, input().split())))) 3 a = sorted(a) 4 if len(a) == 1:print(0) 5 elif len(a) == 2: 6 x = a[1]-a[0] 7 if x % 2 == 0: 8 x = x/2 9 print(int(x)) 10 else:print(x) 11 elif len(a)==3: 12 x = a[1] - a[0] 13 if a[2] - a[1] == x: 14 print(x) 15 else:print(-1) 16 else:print(-1)
python只要先把列表轉換爲集合,再把集合轉換爲列表,一條語句就很方便的完成了去重的過程。不過python真心慢啊,時長用了c++的四倍。
C題
沒錯,又是一道模擬題,我這種菜雞也就只能寫寫這種模擬題了。首先算一下全部食物至多可以堅持多少個星期,而後再對從週一到週日出發七種狀況進行模擬,得出最長天數就行了
1 #include <bits/stdc++.h> 2 using namespace std; 3 int a,b,c; 4 char w[8]={'.','a','b','c','a','c','b','a'}; 5 int getday(int d){ #d爲1到7,分別表示週一到週日 6 int a1=a,b1=b,c1=c; #存儲去除整週以後剩餘的食物 7 int cnt=0; 8 while(1){ 9 if(w[d]=='a'){ 10 if(a1==0)break; 11 else{ 12 a1--;cnt++; 13 } 14 } 15 else if(w[d]=='b'){ 16 if(b1==0)break; 17 else{ 18 b1--;cnt++; 19 } 20 } 21 else{ 22 if(c1==0)break; 23 else{ 24 c1--;cnt++; 25 } 26 } 27 if(d==7)d=1; #表示已經到週日了,下一天應該是週一 28 else d++; 29 } 30 return cnt; 31 } 32 int main(){ 33 scanf("%d%d%d",&a,&b,&c); 34 int i1=a/3,i2=b/2,i3=c/2; 35 int i=min(i1,i2);i=min(i,i3); 36 long long day=7*i; 37 a-=3*i;b-=2*i;c-=2*i; 38 int ma=0; 39 for(int i=1;i<=7;i++){ 40 if(getday(i)>ma)ma=getday(i); 41 } 42 day+=ma; 43 printf("%lld",day); 44 return 0; 45 }
老師說一個厲害的程序員,main函數應該是至關整潔的。像這種對不一樣狀況模擬取最優值的狀況,儘可能的用函數去寫吧。
D題
這道題是一條普通的的貪心。只要想清楚一個問題就行了,在有陽光照射的地方,若是用電池,電池減一但收集器加一,也就是沒有損耗,但若是用收集器,總能量就減一,爲了儘可能跑的遠,就須要儘量的在有陽光的地方用電池,這樣一來,在沒有陽光的地方,就須要儘量的不用電池。注意,收集器有最大容量。
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int maxn=2e5+5; 4 int m[maxn]; 5 int n,b,a; 6 int flag=1; 7 #define scan(i) scanf("%d",&i) 8 int main(){ 9 scan(n);scan(b);scan(a); 10 for(int i=1;i<=n;i++)scan(m[i]); 11 int i;int a1=a; 12 for(i=1;i<=n;i++){ 13 if(a1==0&&b==0){ 14 flag=0; 15 cout<<(i-1);break; 16 } 17 if(m[i]==1){ 18 if(b&&a1<a){ 19 b--;a1++; 20 } 21 else{ 22 a1--; 23 } 24 } 25 else{ 26 if(a1)a1--; 27 else b--; 28 } 29 if(a1==0&&b==0){ 30 flag=0; 31 cout<<i;break; 32 } 33 } 34 if(flag)cout<<n; #wa了一次,就是由於沒有這條語句。忘記了走徹底部路程以後的輸出。 35 return 0; 36 }
看到這題,想起來上學期期末那段時間寫的一道dp,也是一個路程中能量補給的問題。(話說那段時間是真輕鬆,整個一月幾乎沒課,期末考又沒壓力,偷偷帶了電腦寫代碼^-^)
Time Limit: 1000/1000 MS (Java/Others)
Memory Limit: 32768/32768 K (Java/Others)
這道題,當時想了很久。這是我第一次知道動態規劃這個東西。本身寫的時候,就當作貪心來處理,果不其然的wa了,還滿覺得本身想的沒錯,我在每走一步以前都選擇的是到下一步時間最短的方法,
最後的總時長理應也是最短的呀。好吧,當時的想法真愚蠢。貪心算法大概,就是「鼠目寸光」吧,只想着眼前的利益,卻忘了要獲得的是什麼,而用動態規劃的話,大概就是「指揮若定,決勝千里」的感受
吧,只要保證最後結果最優化。中間的某一些點之間或許沒有貪心獲得的效果好,但這一點小犧牲是爲了換取更大的利益。運籌學真的是一門很深的學問,有機會必定要好好鑽研。
狀態轉移方程很簡單 dp[i]=min(dp[i],dp[j]+time) j<i 其他的一些附加條件計算稍微繁瑣一點,當心寫就行了。
1 #include <iostream> 2 using namespace std; 3 int path[102]; 4 double dp[102]; 5 int main() { 6 int L, N, C, T, vr, vt1, vt2; 7 while (cin >> L) { 8 cin >> N >> C >> T; 9 cin >> vr >> vt1 >> vt2; 10 for (int i = 1; i <= N; ++i) 11 cin >> path[i]; 12 path[0] = 0; path[N + 1] = L; 13 dp[0] = 0; 14 for(int i=1;i<=N+1;i++){ 15 double min=1000000; 16 for(int j=0;j<i;++j){ 17 double temp; 18 if(path[i]-path[j]>=C) 19 temp = dp[j] + C * 1.0 / vt1 + (path[i] - path[j] - C)*1.0 / vt2; 20 else 21 temp=dp[j]+(path[i]-path[j])*1.0/vt1; 22 if(j>0) 23 temp+=T; 24 if(temp<min) 25 min=temp; 26 } 27 dp[i] = min; 28 } 29 double rt; 30 rt = L * 1.0 / vr; 31 if(dp[N+1]<rt) 32 cout<<"What a pity rabbit!"<<endl; 33 else 34 cout<<"Good job,rabbit!"<<endl; 35 } 36 return 0; 37 }
E題
仍是模擬。。。。。終於用了一回上學期學過的手寫鏈表,雖然會有一點麻煩,皮一下依然很開心。這題主要要說的,就是如何快速,找到當前狀況下存在的最大值,和最大值對應的下標。
用一個check數組保存每個值的狀態,這樣在尋找最大值的時候,能夠從n開始,若是這個值已經被用過了,就減一再判斷,直到找到當前未用的最大值。而後用position數組保存每個值的下標,方便索引。
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int maxn=2e5+5; 4 int n,k,x; 5 struct node{ 6 int val; 7 int id; 8 node *pre; 9 node *next; 10 }; 11 node p[maxn]; 12 int ans[maxn]; 13 int position[maxn]; 14 bool check[maxn]; 15 inline void build(){ 16 for(int i=1;i<=n;i++){ 17 scanf("%d",&x); 18 p[i].val=x; 19 p[i].id=i; 20 p[i].pre=&p[i-1];p[i].next=&p[i+1]; 21 if(i==1)p[i].pre=NULL; 22 if(i==n)p[i].next=NULL; 23 position[x]=i; 24 } 25 return; 26 } 27 int main(){ 28 scanf("%d%d",&n,&k); 29 build(); 30 int ma=n; 31 int an=1; 32 while(ma!=0){ 33 check[ma]=true; 34 ans[position[ma]]=an; 35 int po=position[ma]; 36 int k1=k;int k2=k; 37 int p1=po,p2=po; 38 while(k1--){ 39 if(p[po].next==NULL)break; 40 int v=p[po].next->val; 41 check[v]=true; 42 ans[position[v]]=an; 43 p1=p[po].next->id; 44 p[po].next=p[po].next->next; 45 } 46 while(k2--){ 47 if(p[po].pre==NULL)break; 48 int v=p[po].pre->val; 49 check[v]=true; 50 ans[position[v]]=an; 51 p2=p[po].pre->id; 52 p[po].pre=p[po].pre->pre; 53 } 54 if(p[p1].next!=NULL)p1=p[p1].next->id; 55 else p1=n+1; 56 if(p[p2].pre!=NULL)p2=p[p2].pre->id; 57 else p2=0; 58 if(p1<=n&&p2>=1){ 59 p[p1].pre=&p[p2]; 60 p[p2].next=&p[p1]; 61 } 62 if(p1<=n&&p2<1)p[p1].pre=NULL; 63 if(p1>n&&p2>=1)p[p2].next=NULL; 64 if(an==1)an=2;else an=1; 65 while(check[ma])ma--; 66 } 67 for(int i=1;i<=n;i++) 68 printf("%d",ans[i]); 69 return 0; 70 }
未完待續。。。。。。