PKU演習問メモ(6/11)
久しぶりすぎて表のフォーマット忘れた(ぁ
No. | 問題名 | 問題の種類および解法 | 難易度 |
---|---|---|---|
3047 | Bovine Birthday | 曜日計算 | ★☆☆☆☆ |
1188 | Gleaming the Cubes | 区間の交わり | ★☆☆☆☆ |
2643 | Election | シミュレーション | ★☆☆☆☆ |
2263 | Heavy Cargo | 貪欲法 | ★☆☆☆☆ |
2624 | 4th Point | 幾何 | ★☆☆☆☆ |
3047 Bovine Birthday
問題概要
与えられた年月日の曜日を求めよ。
解法
Zellerの公式を用いると楽。
ソースコード
int main() { char day[][9]={"satur","sun","mon","tues","wednes","thurs","fri"}; int y,m,d,j,k,h; cin>>y>>m>>d; if(m<3)m+=12,y--; j=y/100,k=y%100; h=(d+int((m+1)*2.6)+k+k/4+j/4+5*j)%7; cout<<day[h]<<"day"<<endl; return 0; }
1188 Gleaming the Cubes
問題概要
n個の立方体について、角の座標(x[i],y[i],z[i])および一辺の長さa[i]が与えられる。
それぞれの立方体は、角の座標からx軸,y軸,z軸のそれぞれの正の方向に、座標軸に平行に辺が伸びている。
このときn個の立方体の交わりの体積を求めよ。
解法
区間[a1,b1]と[a2,b2]の交わりは[max(a1,a2),min(b1,b2)]である。この交わりを取る操作をx,y,zの各成分ごとに行っていけばよい。
ソースコード
int main() { int n; while(cin>>n,n) { int M[3],m[3]; rep(i,3)M[i]=inf,m[i]=-inf; rep(i,n) { int p[3],a; rep(j,3)cin>>p[j]; cin>>a; rep(j,3)M[j]=min(M[j],p[j]+a),m[j]=max(m[j],p[j]); } int ans=1; rep(i,3)ans*=max(0,M[i]-m[i]); cout<<ans<<endl; } return 0; }
2643 Election
問題概要
選挙の候補n人の、名前と所属政党が与えられる。
m票の投票が与えられたとき、当選者の所属政党を答えよ。
ただし、無効票はどの候補の票にもならず、結果が引き分けならば"tie"と出力せよ。
解法
mapで候補の番号を記憶しておくとよい。候補は20人なので線形探索でも余裕かな?
AC少ないからTLE厳しいのかと思ってchar[]でやったが単にWAが多いだけだった。
多分無効票の処理ではまった人が多いのだろう。
ソースコード
struct S{ char str[81]; bool operator<(const S &r)const { return strcmp(str,r.str)<0; } }; int main() { int n,m; char party[20][81]; map<S,int> toi; scanf("%d ",&n); S tmp; rep(i,n) { gets(tmp.str); gets(party[i]); toi[tmp]=i; } scanf("%d ",&m); int vote[20]={0},winner=-1,mx,cnt=0; rep(i,m) { gets(tmp.str); if(toi.count(tmp))vote[toi[tmp]]++; } mx=*max_element(vote,vote+n); rep(i,n)if(vote[i]==mx) { winner=i; cnt++; } printf("%s\n",cnt==1?party[winner]:"tie"); return 0; }
2263 Heavy Cargo
問題概要
各都市と都市の間を結ぶ道路にはそれぞれ重量制限がある。
この制限を満たして、与えられたスタートの都市からゴールにたどり着く道のうち、最もゆるい重量制限の値を求めよ。
都市の数はn≦200,
道の本数はm≦19900を満たす。
解法
ダイクストラ法の要領で優先度付きキューを使い、ゴールに着くまで最も重量制限のゆるい通路を辿っていけばよい。
グラフには隣接行列を用いるのがよい。
ソースコード
int e[200][200]; int main() { int n,m,cs=0; while(cin>>n>>m,n) { cout<<"Scenario #"<<++cs<<endl; rep(i,n)fill_n(e[i],n,0); int city=0; map<string,int> toi; rep(i,m) { int ia,ib,w; string a,b; cin>>a>>b>>w; if(!toi.count(a))toi[a]=city++; if(!toi.count(b))toi[b]=city++; ia=toi[a]; ib=toi[b]; e[ia][ib]=e[ib][ia]=w; } string s,t; cin>>s>>t; int is=toi[s],it=toi[t]; int mx[200]={0},ans=0; mx[is]=inf; priority_queue<pi> Q; Q.push(mp(inf,is)); while(!Q.empty()) { int c=Q.top().second,cw=Q.top().first; Q.pop(); if(c==it) { ans=cw; break; } rep(i,n) { int nw=min(cw,e[c][i]); if(mx[i]>=nw)continue; mx[i]=nw; Q.push(mp(nw,i)); } } cout<<ans<<" tons"<<endl<<endl; } return 0; }
2624 4th Point
問題概要
平行四辺形の隣り合う2辺の両端の座標が与えられる。
このとき、残りの頂点の座標を求め、小数点以下3桁までの小数に丸めて出力せよ。
解法
まずは与えられた2辺が重なっている頂点を求める。
その頂点をP(p)とすればPに2本の辺のベクトルaとbを加算すれば求める頂点になる。
ソースコード
なんかセンスない実装すぎるなあ。
int main() { P p[4],pp,ans; while(cin>>p[0].real()>>p[0].imag()) { rep(i,3)cin>>p[i+1].real()>>p[i+1].imag(); rep(i,4)rep(j,4)if(i!=j&&abs(p[i]-p[j])<EPS) { pp=p[i]; break; } ans=pp; rep(i,2) { ans+=(abs(p[i*2]-pp)<EPS?p[i*2+1]:p[i*2])-pp; } printf("%.3f %.3f\n",ans.real(),ans.imag()); } return 0; }