JOI予選の問題を解いてみる
現役の時は参加しなかったので、参加するのは去年に引き続き二回目。
準備ができてなかったどころか寝過ごしたのでひどい。
1問目
問題
食事a,b,c,ドリンクd,eが与えられる。食事とドリンクをセットで注文すると50円引きになる。最も安いセットの価格を出力する。
方針
数値a,b,cの中の最小値とd,eの中の最小値を足して50を引いた値を出力する
#include<iostream> #include<cstdio> #include<vector> #include<string> #include<algorithm> using namespace std; int main(){ int a,b,c,d,e; cin>>a>>b>>c>>d>>e; cout<<(min(min(a,b),c)+min(d,e)-50)<<endl; return 0; }
2問目
問題
組み合わせ対戦結果から順位を求める。
方針
スコアでソートして順位を割り振った後に、チームidでソートして出力。
解答
#include<iostream> #include<cstdio> #include<vector> #include<string> #include<algorithm> #include<utility> using namespace std; typedef pair<int,int> PII; int score[100][100]; int main(){ int n; cin>>n; vector<PII> points(n); vector<PII> ranks(n); int a,b,c,d; for(int i=0;i<n*(n+1)/2;i++){ cin>>a>>b>>c>>d; if(c==d){ score[a-1][b-1] = 1; score[b-1][a-1] = 1; } else{ score[a-1][b-1] = c>d?3:0; score[b-1][a-1] = d>c?3:0; } } for(int i=0;i<n;i++){ int p = 0; for(int j=0;j<n;j++){ if(i!=j){ p += score[i][j]; } } points[i] = PII(p,i); } sort(points.begin(),points.end()); reverse(points.begin(),points.end()); int sc = -1,rank = 0; for(int i=0;i<n;i++){ if(points[i].first != sc){ sc = points[i].first; rank = i; } ranks[i] = PII(points[i].second,rank); } sort(ranks.begin(),ranks.end()); for(int i=0;i<n;i++){ cout<<ranks[i].second+1<<endl; } return 0; }
3問目
問題
みんながよくやる金額当たりのカロリーを最大化する問題。基本料金、カロリーが決まっているピザにトッピングを乗せる。トッピングの値段は一律で、カロリーのみが違う。
方針
トッピングのカロリーの大きい順にソートして、トッピングを足していった時の(カロリー/金額)の最大値を取る。
解答
#include<iostream> #include<cstdio> #include<vector> #include<string> #include<algorithm> using namespace std; int main(){ int n,cost1,cost2,cal1; cin>>n; cin>>cost1>>cost2; cin >> cal1; vector<int> cal; int cc; for(int i=0;i<n;i++){ cin>>cc; cal.push_back(cc); } sort(cal.begin(),cal.end()); reverse(cal.begin(),cal.end()); int ans = cal1/cost1; int m = 0; for(int i=0;i<n;i++){ cal1 += cal[i]; cost1 += cost2; ans = cal1/cost1; m = max(ans,m); } cout<<m<<endl; return 0; }
4問目
問題
メニューが3種類あり、いくつかの日食べるメニューは決まっている。
3日続けて同じメニューが現れない条件で、メニューの決め方は何通りあるか。
10000で割った余りを出力する。
方針
前二日のメニュー9通りx日数でDPを掛ける。同じメニューが3日続いていたり、メニューが決まっている日を考慮する。
解答
#include<iostream> #include<cstdio> #include<vector> #include<string> #include<algorithm> using namespace std; int dp[9][100]; int menu[100]; int main(){ for(int i=0;i<9;i++){ for(int j=0;j<100;j++){ dp[i][j] = 0; } } for(int i=0;i<100;i++){ menu[i] = -1; } int n,k; cin>>n>>k; int a,b; for(int i=0;i<k;i++){ cin>>a>>b; menu[a-1] = b-1; } if(menu[0] == -1&&menu[1] == -1){ for(int i=0;i<9;i++){ dp[i][1] = 1; } } else if(menu[1] == -1){ for(int i = 0;i<3;i++){ dp[menu[0]*3+i][1] = 1; } } else if(menu[0] == -1){ for(int i = 0;i<3;i++){ dp[i*3+menu[1]][1] = 1; } } else{ dp[(menu[0])*3+menu[1]][1] = 1; } for(int i=2;i<n;i++){ for(int j=0;j<9;j++){ dp[j][i] = dp[j/3][i-1] + dp[j/3+3][i-1] + dp[j/3+6][i-1]; } dp[0][i] -= dp[0][i-1]; dp[4][i] -= dp[4][i-1]; dp[8][i] -= dp[8][i-1]; if(menu[i] != -1){ for(int j=0;j<9;j++){ if(j%3 != menu[i]) dp[j][i] = 0; } } for(int j=0;j<9;j++){ dp[j][i] %= 10000; } } int sum = 0; for(int j = 0;j<9;j++){ sum+= dp[j][n-1]; } cout<<sum%10000<<endl; return 0; }
問題5
問題
ハニカム構造で出来たマップに建物があり、それを取り囲むイルミネーションの長さを求める問題。
イルミネーションは外から見える場所にのみ設置する。
方針
外側からbfsを掛け、「外側」を特定する。それぞれの建物が「外側」に面している個数を数える。
解答
なぜか01がくっついた文字列の入力だと勘違いしていたのでstringで実装してます。
ハニカム構造ライブラリとか持ってないや。
#include<iostream> #include<cstdio> #include<vector> #include<string> #include<algorithm> #include<queue> using namespace std; typedef pair<int,int> PII; int main(){ int w,h; cin>>w>>h; vector<string> field; string s; for(int i=0;i<h;i++){ string s=""; int a; for(int x=0;x<w;x++){ cin>>a; if(a==0)s+="0"; if(a==1)s+="1"; } field.push_back(s); } queue<pair<int,int> >qu; for(int i=0;i<h;i++){ qu.push(PII(0,i)); qu.push(PII(w-1,i)); } for(int i=0;i<w;i++){ qu.push(PII(i,0)); qu.push(PII(i,h-1)); } while(!qu.empty()){ PII p = qu.front(); qu.pop(); int x = p.first; int y = p.second; if(x>=0 && x<w && y>=0 && y< h){ if(field[y][x] == '0'){ field[y][x] = '-'; qu.push(PII(x+1,y)); qu.push(PII(x-1,y)); qu.push(PII(x,y+1)); qu.push(PII(x,y-1)); if(y%2 == 1){ qu.push(PII(x-1,y+1)); qu.push(PII(x-1,y-1)); } else{ qu.push(PII(x+1,y+1)); qu.push(PII(x+1,y-1)); } } } } for(int y=0;y<h;y++){ for(int x=0;x<w;x++){ if(field[y][x] == '0') field[y][x] = '1'; cout<<field[y][x]; } cout<<endl; } int count = 0; for(int y=0;y<h;y++){ for(int x=0;x<w;x++){ if(field[y][x] == '1'){ int c = 6; if(x<w-1) c -= field[y][x+1] == '1'; if(x>=1) c -= field[y][x-1] == '1'; if(y<h-1) c -= field[y+1][x] == '1'; if(y>=1) c -= field[y-1][x] == '1'; if(y%2 == 1){ if(x>=1){ if(y<h-1) c -= field[y+1][x-1] == '1'; if(y>=1) c -= field[y-1][x-1] == '1'; } } else{ if(x<w-1){ if(y<h-1) c -= field[y+1][x+1] == '1'; if(y>=1) c -= field[y-1][x+1] == '1'; } } count += c; cout<<c<<" "; } else{ cout<<0<<" "; } } cout<<endl; } cout<<count<<endl; return 0; }