【Codeforces #130 Div2】Solutions
【208A ?Dubstep】
http://codeforces.ru/problemset/problem/208/A
題目大意:一個(gè)句子被添加了若干“WUB”,問原句。
將WUB去掉就行了,在句首或句尾直接刪除,在句中替換成空格,注意多個(gè)“WUB”相連時(shí)特判。
#include <iostream> #include <cstdio> #include <cstring> #include <cstdlib> using namespace std;char s[3000]; int len; bool exist;int main(){scanf("%s",&s);len=strlen(s);int i=0;while(true){if(s[i]=='W' && s[i+1]=='U' && s[i+2]=='B') i+=3;else break;}while(true){if(s[len-1]=='B' && s[len-2]=='U' && s[len-3]=='W') len-=3;else break;}while(i<len){if(s[i]=='W' && s[i+1]=='U' && s[i+2]=='B'){i+=3;if(!exist) printf(" ");exist=true;}else{cout<<s[i];i++;exist=false;}}cout<<endl;return 0; }
【208B Solitaire】
http://codeforces.ru/problemset/problem/208/B
題目大意:桌面上n堆牌,牌有數(shù)值和花色兩個(gè)屬性。一堆可以放到另一堆上當(dāng)且僅當(dāng)兩堆牌最上面一張的牌面或花色相同。每次可以將最后一堆第x堆放到第x-1堆或x-3堆(如果存在),問是否存在策略使得所有牌合成一堆。
由于n很小,容易想到搜索。但是O(2^n)顯然難以令人接受。所以考慮對搜索過程記憶化。f[i][a][b][c]表示:當(dāng)前處理第i堆,最后一堆是第a堆,倒數(shù)第二堆是第b堆,倒數(shù)第三堆是第c堆時(shí),是否可以合成一堆,每次搜索后記錄結(jié)果,避免重復(fù)搜索。
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> using namespace std;char card[52][2]; int n,f[53][53][53][53];bool check(char a[2], char b[2]){return a[0]==b[0] || a[1]==b[1]; }bool dfs(int cur,int a,int b,int c){bool res=false;if(cur==1) return true;if(f[cur][a][b][c]) return false;if(check(card[a],card[b]))res|=dfs(cur-1,a,c,cur-3);if(!res && cur-3 && check(card[a],card[cur-3]))res|=dfs(cur-1,b,c,a);return !(f[cur][a][b][c]=!res); }int main(){scanf("%d",&n);memset(f,false,sizeof(f));for(int i=1;i<=n;i++)scanf("%s",&card[i]);if(dfs(n,n,n-1,n-2))printf("YES\n");else printf("NO\n");return 0; }
【208C Police Station】
http://codeforces.ru/problemset/problem/208/c
題目大意:給定N個(gè)節(jié)點(diǎn)M條邊的無向圖,邊權(quán)相同。在圖中選一個(gè)點(diǎn),使得從1到N的最短路上,含有被點(diǎn)覆蓋的邊的數(shù)量的平均值最大。(很別扭,還是看原題吧……)
當(dāng)時(shí)這個(gè)題很少有做的,可能是因?yàn)椴缓孟搿?/p>
首先他要求最短路,其次還要求出最短路的數(shù)量,然后還要知道每個(gè)點(diǎn)分別在多少條最短路徑上。
最短路可以用Floyd來求,記為sp;數(shù)量可以用DP,f[i][j]表示從1出發(fā)走j步到達(dá)i的方案數(shù),f[i][j]=Σf[u][j-1],u→i;最后求經(jīng)過每個(gè)點(diǎn)有多少條最短路,可能讓人感覺比較麻煩,其實(shí)也很簡單的。用g[i][j]再統(tǒng)計(jì)一下從n出發(fā)的方案數(shù),方程跟f[i][j]的一樣,那么對于一點(diǎn)x,經(jīng)過他的最短路條數(shù)num就是f[i][j]*g[i][sp-dist[i][j]]。此外還有一個(gè)問題就是,如果這個(gè)點(diǎn)選在2~N上,每個(gè)點(diǎn)將覆蓋最短路上的兩條邊;而如果選在1或N上,只能覆蓋最短路上的一條邊。
#include <iostream> #include <cstdio> #include <cstring> #include <cstdlib> #include <queue> using namespace std; template<class T>inline void gmax(T &a,T b){if(a<b)a=b;}int n,m,x,y,sp,dist[200],f[200][200],g[200][200],map[200][200],ans; bool vis[200]; double res;struct EDGE{int pnt;EDGE *pre;EDGE(){}EDGE(int _pnt,EDGE *_pre):pnt(_pnt),pre(_pre){} }Edge[20000],*SP=Edge,*edge[200];inline void addedge(int a,int b){edge[a]=new(++SP)EDGE(b,edge[a]);edge[b]=new(++SP)EDGE(a,edge[b]); } int main(){scanf("%d%d",&n,&m);for(int i=1;i<=m;i++){scanf("%d%d",&x,&y);addedge(x,y);map[x][y]=map[y][x]=1;}for(int k=1;k<=n;k++)for(int i=1;i<=n;i++)if(map[i][k])for(int j=1;j<=n;j++)if(map[k][j])if(!map[i][j] || map[i][j]>map[i][k]+map[k][j])map[i][j]=map[i][k]+map[k][j];sp=map[1][n];f[1][0]=1;for(int i=0;i<sp;i++)for(int j=1;j<=n;j++)for(EDGE *k=edge[j];k;k=k->pre)f[k->pnt][i+1]+=f[j][i];g[n][0]=1;for(int i=0;i<sp;i++)for(int j=1;j<=n;j++)for(EDGE *k=edge[j];k;k=k->pre)g[k->pnt][i+1]+=g[j][i];for(int i=2;i<n;i++)if(map[1][i]+map[i][n]==sp) gmax(ans,f[i][map[1][i]]*g[i][map[i][n]]);ans<<=1;gmax(ans,f[n][sp]);res=(double)ans/(double)f[n][sp];printf("%.12lf\n",res);return 0; }
【204D Prizes,Prizes,more Prizes】
http://codeforces.ru/problemset/problem/208/d
題目大意:好像是吃什么東西,每吃一個(gè)就會得到多少積分(就像方便面里面兌換卡一樣)。有五種獎品,需要積分abcde,主人公一包一包吃,攢到能兌換獎品就去兌換,并且先兌換價(jià)值最大的,問最后能兌到五種獎品各多少,還能剩下多少積分。
這個(gè)題爛大街了,rating和第一題已經(jīng)差不多了。
就是把積分累加、累加、累加……低于最小獎品價(jià)值的時(shí)候就去兌獎,從高往低兌,能兌多少對多少。兌換的時(shí)候不能暴力模擬,會TLE。
#include <iostream> #include <cstdio> #include <cstring> #include <cstdlib> using namespace std;long long n,a[100],b[100],s[100],cur;long long exchange(long long x){for(int i=5;i>0;i--)b[i]+=x/a[i],x-=(x/a[i]*a[i]);return x; }int main(){cin>>n;for(int i=1;i<=n;i++)cin>>s[i];cin>>a[1]>>a[2]>>a[3]>>a[4]>>a[5];cur=0;for(int i=1;i<=n;i++){cur+=s[i];if(cur>=a[1]) cur=exchange(cur);}for(int i=1;i<5;i++) cout<<b[i]<<" ";cout<<b[5]<<endl;cout<<cur<<endl;return 0; }
【208E Blood Cousins】
http://codeforces.ru/problemset/problem/208/e
題目大意:給你若干顆樹,若干個(gè)詢問(x,y),回答在含有結(jié)點(diǎn)x的樹中有多少結(jié)點(diǎn)z,使得x和z關(guān)于他們LCA的深度為y。
。。。。。。srO kAc Orz。。。。。。
kAc教的什么樹套樹、函數(shù)式線段樹都不會寫……只會寫一個(gè)二分。
首先用倍增法求LCA,然后求LCA下面深度為y的結(jié)點(diǎn)個(gè)數(shù)。
對于統(tǒng)計(jì)這一步,可以用dfs序來搞。把時(shí)間戳按結(jié)點(diǎn)深度壓一個(gè)vector,每次詢問的時(shí)候,在與x同深度的時(shí)間戳序列里面二分,找到進(jìn)入LCA子樹與離開LCA子樹的時(shí)間戳之間的節(jié)點(diǎn)個(gè)數(shù),再減去x自己,就是答案。
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <vector> #include <algorithm> #define MN 100010 using namespace std;vector<int> pos[MN],t; int n,m,x,y,deep[MN],l[MN],r[MN],idx,fa[MN][20];struct EDGE{int pnt;EDGE *pre;EDGE(){}EDGE(int _pnt,EDGE *_pre):pnt(_pnt),pre(_pre){} }Edge[MN],*SP=Edge,*edge[MN];inline void addedge(int a,int b){edge[a]=new(++SP)EDGE(b,edge[a]); }void dfs(int x,int dep){deep[x]=dep;pos[dep].push_back(idx);l[x]=idx++;for(EDGE *j=edge[x];j;j=j->pre)dfs(j->pnt,dep+1);r[x]=idx; }int main(){scanf("%d",&n);for(int i=1;i<=n;i++){scanf("%d",&fa[i][0]);addedge(fa[i][0],i);}dfs(0,0);for(int j=1;j<17;j++)for(int i=1;i<=n;i++)fa[i][j]=fa[fa[i][j-1]][j-1];scanf("%d",&m);while(m--){scanf("%d%d",&x,&y);t=pos[deep[x]];for(int i=0;i<17;i++)if(y>>i&1) x=fa[x][i];printf("%d ",x?lower_bound(t.begin(),t.end(),r[x])-lower_bound(t.begin(),t.end(),l[x])-1:0);}return 0; }
轉(zhuǎn)載于:https://www.cnblogs.com/Delostik/archive/2012/07/24/2606914.html
總結(jié)
以上是生活随笔為你收集整理的【Codeforces #130 Div2】Solutions的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [Java] webservice so
- 下一篇: jvisualvm使用