2018 ACM-ICPC World Finals - Beijing
2018 ACM-ICPC World Finals - Beijing
A. Catch the Plane
\(dp[v_i,t_i]\)表示時(shí)刻\(t_i\)在\(v_i\)點(diǎn),到達(dá)終點(diǎn)的最大概率,那么轉(zhuǎn)移方程為:
\(dp[(v_i,t_i)] = max(P_{ij}*dp[(v_{j+1},t_{j+1})] + (1-Pij)*dp[(v_{i+1},t_{i+1})])\)
\(dp[(v_i,t_i)] = max(dp[v_{i+1},t_{i+1}])\)
其中\((v_i,t_i)\)的一個(gè)后繼狀態(tài)為\((v_j,t_j)\)兩個(gè)狀態(tài)之間的轉(zhuǎn)移概率為\(P_{ij}\),第一種轉(zhuǎn)移:沿\(P_{ij}\)這個(gè)方向轉(zhuǎn)移,以及繼續(xù)留在這個(gè)點(diǎn)等待下次轉(zhuǎn)移(\((v_{i+1},t_{i+1})\)為同一位置下與\(t_i\)最接近的下一個(gè)時(shí)間);第二種轉(zhuǎn)移是:直接選擇繼續(xù)等待的概率。想出這些后,以為可以愉快的ac了。然而調(diào)到早上7點(diǎn)。。。才弄好
- 問(wèn)題一:%I64d讀1e18,蜜汁爆了,換了幾個(gè)編譯器才發(fā)現(xiàn)。。。
- 問(wèn)題二:為簡(jiǎn)化代碼省略了討論,導(dǎo)致后面一個(gè)點(diǎn)wa
- 問(wèn)題三:起點(diǎn)和終點(diǎn)要單獨(dú)加進(jìn)去,導(dǎo)致后面一個(gè)點(diǎn)wa
B. Comma Sprinkler
這題沒(méi)什么難度,把單詞取出來(lái)直接搜索即可。
#include <bits/stdc++.h> #define pb push_back typedef long long ll; const int N = 1000100; using namespace std; string s, word[N]; int cnt; void chai(string s) {int n = s.size();cnt = 1;for(int i=0;i<n;++i) {if(s[i]==' '){word[cnt] += ' ';++cnt;}elseword[cnt]+=s[i];} } map< string,vector<string> > pre,last; string delco(string s) {string t;t.clear();for(auto c: s) if(c>='a'&&c<='z') t+=c;return t; } int iscolst(string s) {int t = s.size()-1;while(t>=0){if(s[t]==',')return 1;--t;}return 0; } int isbiaolst(string s) {int t = s.size()-1;while(t>=0){if(s[t]=='.'||s[t]==',')return 1;--t;}return 0; } map<string,bool> vispre,vislst; void X(string s); void Y(string s); void X(string s) {vislst[s] = 1;for(int x=0;x<last[s].size();++x) if(!vispre[last[s][x]]) Y(last[s][x]); } void Y(string s) {vispre[s] = 1;for(int x=0;x<pre[s].size();++x) if(!vislst[pre[s][x]]) X(pre[s][x]); } string update(string s) {s+=',';int t=s.size()-1;swap(s[t],s[t-1]);return s; } int main() {getline(cin,s); chai(s);for(int i=2;i<=cnt;++i) if(!isbiaolst(word[i-1])){pre[delco(word[i])].pb(delco(word[i-1]));}for(int i=1;i<cnt;++i) if(!isbiaolst(word[i])){last[delco(word[i])].pb(delco(word[i+1]));}for(int i=1;i<cnt;++i) {string t = delco(word[i]);if(!vislst[t]&&iscolst(word[i]))X(t);}for(int i=2;i<=cnt;++i) {string t=delco(word[i]);if(!vispre[t]&&iscolst(word[i-1])) Y(t);}for(int i=1;i<=cnt;++i) {string t = delco(word[i]);if(vislst[t]&&!isbiaolst(word[i]))cout << update(word[i]);elsecout << word[i];}puts("");return 0; }F. Go with the Flow
把單詞的長(zhǎng)度記錄下來(lái),模擬放單詞,把所有位置上是空格的位置按從上到下存起來(lái)。順序dp求出每個(gè)位置向上最長(zhǎng)走多遠(yuǎn),dp過(guò)程中取最大值即可,這樣復(fù)雜度與空格數(shù)成正比,看大佬代碼學(xué)習(xí)了一下,巧妙地解決了dp數(shù)組的開(kāi)法用一維存,這樣空間就不隨著寬度變化。一開(kāi)始寫(xiě)的暴力bfs炸的妥妥的。
#include <bits/stdc++.h> #define rep(i,a,b) for(int i=a;i<=b;++i) #define PII pair<int,int> #define MP make_pair #define fr first #define sc second typedef long long ll; const int N = 5600; using namespace std; int n,L[N],len; char s[88]; PII A[N]; int cnt,f[N*188];void cal_A(int w) {int x=1,y=0;cnt=0;rep(j,1,n) {if(y+L[j]<=w){if(y)A[++cnt]=MP(x,y);y+=L[j]+1;}else {++x;y=L[j]+1;}} } int cal_id(int x,int y,int m) {if(x<1)return 0;if(y<1||y>m)return 0;return (x-1)*m + y; } int main() {int MX = 0;scanf("%d",&n);for(int i=1;i<=n;++i) {scanf(" %s",s);L[i]=strlen(s);MX = max(MX,L[i]);len += L[i];}len += (n-1);int ans=0,ans1=0,tmp;rep(i,MX,len) {cal_A(i);tmp = 0;rep(j,1,cnt){int x=A[j].fr, y=A[j].sc;f[cal_id(x,y,i)] = max(f[cal_id(x-1,y-1,i)],f[cal_id(x,y,i)]);f[cal_id(x,y,i)] = max(f[cal_id(x-1,y,i)],f[cal_id(x,y,i)]);f[cal_id(x,y,i)] = max(f[cal_id(x-1,y+1,i)],f[cal_id(x,y,i)]);++f[cal_id(x,y,i)];tmp = max(tmp,f[cal_id(x,y,i)]);}if(tmp>ans){ans=tmp;ans1=i;}rep(j,1,cnt)f[cal_id(A[j].fr,A[j].sc,i)]=0;}printf("%d %d\n",ans1,ans);return 0; }K. Wireless is the New Fiber
貪心,首先答案是一棵樹(shù),既有n-1條邊,所以要減少的總邊數(shù)固定,所以我們盡量要改變度數(shù)大的點(diǎn),換一句話一定先滿足分叉少的。現(xiàn)在考慮如何滿足,注意到度數(shù)為1的點(diǎn)是很特殊的,我們一定要先滿足他們,并且最好他們不互相連接,那就把他們接在其他度數(shù)較小的點(diǎn)上,顯然最好不接滿。我們已經(jīng)確定,如果有度為1的點(diǎn),一定要先滿足它,那么考慮如何把度非1的點(diǎn)轉(zhuǎn)換為度為1的點(diǎn),顯然就是把度數(shù)為1的點(diǎn)接上去使他恰好多余一個(gè)位置,這些點(diǎn)組成的集合便是一個(gè)新的度為1的點(diǎn),如此反復(fù)到無(wú)法產(chǎn)生新的度為1的點(diǎn)集。接下來(lái)我們?nèi)匀粌?yōu)先滿足度數(shù)小的點(diǎn),先把所有的1接上去,剩下的位置怎么辦,我用度數(shù)最大的點(diǎn)接上去,把他們當(dāng)作度數(shù)為1的點(diǎn),為什么?因?yàn)檫@些點(diǎn)的度數(shù)最大,可以盡可能的把減少的邊用在他們身上,重復(fù)上述操作,直到不足以產(chǎn)生新的度數(shù)為1的點(diǎn)集。最后把剩余的點(diǎn)全部加到當(dāng)前節(jié)點(diǎn)上。如果最終有多個(gè)的度數(shù)為1的點(diǎn)集,那把他們?nèi)我膺B成一棵樹(shù)樹(shù)即可。這題的貪心,我之前一直在胡寫(xiě),也沒(méi)證明出來(lái)做法的正確性。。GG。。。。膜了大佬的寫(xiě)法。
#include <bits/stdc++.h> #define rep(i,a,b) for(int i=(a);i<=(b);++i) #define pb push_back typedef long long ll; const int N = 10000 + 10; using namespace std; int n,m,d[N]; vector<int> G[N]; void add(int u,int v) {G[u].pb(v);} struct node {int id,d;node(){}node(int a,int b){id=a,d=b;} }a[N]; int b[N]; int cnt,cnt0; bool cmp(node a,node b) {return a.d < b.d;} vector<int> v; int main() {scanf("%d%d",&n,&m);rep(i,1,m) {int x,y;scanf("%d%d",&x,&y);++d[x],++d[y];}for(int i=0;i<n;++i) a[cnt++] = node(i,d[i]);sort(a,a+cnt,cmp);for(int i=0;i<cnt;++i) {if(a[i].d==1) v.push_back(a[i].id);else if(v.size() >= a[i].d-1){for(int j=0;j<a[i].d-1;++j) {add(a[i].id,v[v.size()-1]);v.pop_back();}v.push_back(a[i].id);}else if(v.size()+cnt-i-1>=a[i].d-1){for(int j=0;j<v.size();++j) {add(v[j],a[i].id);}for(int j=0;j<a[i].d-1-v.size();++j){add(a[i].id,a[--cnt].id);}v.clear();v.push_back(a[i].id);}else {for(int j=0;j<v.size();++j){add(a[i].id,v[j]);}for(int j=i+1;j<cnt;++j){add(a[i].id,a[j].id);}v.clear();break;}}if(v.size()>0){for(int i=1;i<v.size();++i){add(v[0],v[i]);}}for(int i=0;i<n;++i){for(int j=0;j<G[i].size();++j) {--d[i],--d[G[i][j]];}}int num=0;rep(i,0,n-1)if(d[i])++num;printf("%d\n",num);printf("%d %d\n",n,n-1);rep(i,0,n-1){rep(j,0,(int)G[i].size()-1) {printf("%d %d\n",i,G[i][j]);}}return 0; }轉(zhuǎn)載于:https://www.cnblogs.com/RRRR-wys/p/9236861.html
總結(jié)
以上是生活随笔為你收集整理的2018 ACM-ICPC World Finals - Beijing的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 历史上的宋江起义 宋江起义介绍
- 下一篇: 水蛭养殖前景怎么样 大家一起来了解吧