intさわだんのBlack History

刹那的レジェンドになりたい。

2014 情報オリンピック 予選  参加記

あとから見れるようにソースはっとく。

本番のソースそのままはるからとても見にくいと思われます。

競技前、風邪がやばいな~~と思っていた。

高校入試と同じように ももいろクローバーZの「行くぜっ!怪盗少女」を聞く。
この曲を聞くとなぜか緊張がおさまる。

一応言っておくと、別にももクロそんな好きじゃないです。嫌いでもないけど。

競技開始。

1

#include <bits/stdc++.h>

using namespace std;



int main(){

	int a,b,c,d,p;
	cin >> a >> b >> c >> d >> p;

	int x = p*a;
	int y = b;
	if(p > c)y += (p-c)*d;
	cout << min(x,y) << endl;
	return 0;
}

2

#include <bits/stdc++.h>

using namespace std;

int n,m,ans[300];
int t[300];

int main(){
	cin >> n >> m;
	for(int i = 0;i < m;i++){
		cin >> t[i];
	}
	for(int i = 0;i < m;i++){
		int ha = 0;
		for(int j = 1;j <= n;j++){
			int y;
			cin >> y;
			if(t[i] == y){
				ans[j]++;
			}else{
				ha++;
			}
		}
		ans[t[i]] += ha;
	}
	for(int i = 1;i <= n;i++){
		cout << ans[i] << endl;
	}
	return 0;
}

3

#include <bits/stdc++.h>

using namespace std;

int h,w;
char s[300][300];

int main(){
	cin >> h >> w;

	for(int i = 0;i < h;i++){
		cin >> s[i];
	}

	for(int i = 0;i < h;i++){
		for(int j = 0;j < w;j++){
			int ans =0;
			for(int k = j;k >= 0;k--,ans++){
				if(s[i][k] == 'c'){
					cout << ans;
					goto out;
				}
			}
			cout << -1;
			out:
			;
			if(j != w-1)cout << " ";
		}
		cout << endl;
	}
	return 0;
}

4

#include <bits/stdc++.h>

using namespace std;
typedef long long int ll;
const long long int  INF = 1000000000000;
ll n,m;
ll d[1300],c[1300];
ll dp[2000][2000];
int main(){
	for(int i = 0;i <= 1200;i++){
		for(int j = 0;j <= 1200;j++){
			dp[i][j] = INF;
		}
	}
	cin >> n >> m;
	for(int i = 1;i <= n;i++){
		cin >> d[i];
	}
	for(int i = 1;i <= m;i++){
		cin >> c[i];
	}
	for(int i = 0;i <= 1200;i++){
		dp[i][0] = 0;
	}
	for(int i = 1;i <= m;i++){
		for(int j = 1;j <= n;j++){
			dp[i][j] = min(dp[i-1][j],dp[i-1][j-1]+d[j]*c[i]);
		}
	}

	cout << dp[m][n] << endl;

	return 0;
}

ここまでで大体40分ぐらい。さすがに簡単過ぎて4完では若干不安があったので、"絶対問題5解こうな"ってなる。


問題5見る。
なるほど、やるだけだな。
書く。

#include <bits/stdc++.h>

using namespace std;

int h,w;
char s[1300][1300];
int d[1300][1300];
int ans = 0;
int da[] = {1,1,1,0,-1,-1,-1,0};
int db[] = {1,0,-1,-1,-1,0,1,1};
bool flag;

void ch(int a,int b){
	int co = 0;
	for(int i = 0;i < 8;i++){
		int na = a + da[i];
		int nb = b + db[i];
		if(na >= 0 && na < h && nb >= 0 && nb < w && d[na][nb] <= 0 && ans >= abs(d[na][nb]))co++;
	}
	if(co >= d[a][b]){
		d[a][b] = 0;
		d[a][b] -= (ans+1);
		flag = true;
	}
}
int main(){
	cin >> h >> w;
	for(int i = 0;i < h;i++){
		cin >> s[i];
	}
	for(int i = 0;i < h;i++){
		for(int j = 0;j < w;j++){
			if(s[i][j] == '.'){
				d[i][j] = 0;
			}else{
				d[i][j] = s[i][j] - '0';
			}
		}
	}
	flag = true;
	while(flag){
		flag = false;
		for(int i = 0;i < h;i++){
			for(int j = 0;j < w;j++){
				if(d[i][j] > 0) ch(i,j);
			}
		}
		if(flag == true)ans++;
	}

	cout << ans << endl;

	return 0;
}

コンパイルして実行する。
あれ、テストケース2の計算がまったく終わらない・・・なぜだ。

ちょっと考える。

ちょっと無駄な計算を省いて書く。

#include <bits/stdc++.h>

using namespace std;

int h,w;
char s[1300][1300];
int d[1300][1300];
int sa[1300][1300];
int ans = 0;
int da[] = {1,1,1,0,-1,-1,-1,0};
int db[] = {1,0,-1,-1,-1,0,1,1};
bool flag;

void ch(int a,int b){
	int co = 0;
	for(int i = 0;i < 8;i++){
		int na = a + da[i];
		int nb = b + db[i];
		if(na >= 0 && na < h && nb >= 0 && nb < w && d[na][nb] <= 0 && ans >= abs(d[na][nb]))co++;
	}
	if(co >= d[a][b]){
		d[a][b] = 0;
		d[a][b] -= (ans+1);
		flag = true;
	}
}
int main(){
	scanf("%d%d",&h,&w);
	for(int i = 0;i < h;i++){
		scanf("%s",s[i]);
	//	cin >> s[i];
	}
	for(int i = 0;i < h;i++){
		for(int j = 0;j < w;j++){
			if(s[i][j] == '.'){
				d[i][j] = 0;
				for(int k = 0;k < 8;k++){
					int aa = i + da[k];
					int bb = j + db[k];
					if(aa >= 0 && aa < h && bb >= 0 && bb < w)sa[aa][bb]++;
				}
			}else{
				d[i][j] = s[i][j] - '0';
			}
		}
	}
	flag = true;
	while(flag){
		flag = false;
		int ad[1200][1200] = {0};
		for(int i = 0;i < h;i++){
			for(int j = 0;j < w;j++){
				if(d[i][j] > 0 && sa[i][j] >= d[i][j]){
					flag = true;
					d[i][j] = 0;
					for(int k = 0;k < 8;k++){
						int aa = da[k] + i;
						int bb = db[k] + j;
						if(aa >= 0 && aa < h && bb >= 0 && bb < w)ad[aa][bb]++;
					}
				}
			}
		}
		for(int i = 0;i < h;i++){
			for(int j = 0;j < w;j++){
				sa[i][j] += ad[i][j];
			}
		}
		if(flag == true)ans++;
	}

	cout << ans << endl;

	return 0;
}

結果変わらずテストケース2の計算がまったく終わらない。

若干あせる。

冷静に考察する。

あ、これ幅優先探索ジャンw

書く。

#include <bits/stdc++.h>

using namespace std;
typedef pair<int,int> P;
const int INF = 1000000000;
int h,w;
char s[1300][1300];
int d[1300][1300];
int ka[1300][1300];
int sa[1300][1300];
int ans = 0;
int da[] = {1,1,1,0,-1,-1,-1,0};
int db[] = {1,0,-1,-1,-1,0,1,1};
bool flag;

void ch(int a,int b){
	int co = 0;
	for(int i = 0;i < 8;i++){
		int na = a + da[i];
		int nb = b + db[i];
		if(na >= 0 && na < h && nb >= 0 && nb < w && d[na][nb] <= 0 && ans >= abs(d[na][nb]))co++;
	}
	if(co >= d[a][b]){
		d[a][b] = 0;
		d[a][b] -= (ans+1);
		flag = true;
	}
}
int main(){
	queue<P> que;
	scanf("%d%d",&h,&w);
	for(int i = 0;i < h;i++){
		scanf("%s",s[i]);
	//	cin >> s[i];
	}
	for(int i = 0;i < h;i++){
		for(int j = 0;j < w;j++){
			ka[i][j] = INF;
			if(s[i][j] == '.'){
				d[i][j] = 0;
				ka[i][j] = 0;
				que.push(P(i,j));
			}else{
				d[i][j] = s[i][j] - '0';
			}
		}
	}

	while(que.size()){
		P p = que.front(); que.pop();
		int a = p.first;
		int b = p.second;
		for(int i = 0;i < 8;i++){
			int aa = a + da[i];
			int bb = b + db[i];
			if(aa >= 0 && aa < h && bb >= 0 && bb < w &&  ka[aa][bb] == INF){
				sa[aa][bb]++;
				if(sa[aa][bb] >= d[aa][bb]){
					ka[aa][bb] = ka[a][b]+1;
					que.push(P(aa,bb));
					ans = max(ans,ka[aa][bb]);
				}
			}
		}
	}
	cout << ans << endl;

	return 0;
}

無駄な変数や関数などがありますが・・・

なんとか書いて全部答えが出て安心する。

あと残り一時間。どうする。

問題6とりあえず見る。

やばそう。解法わかりそうでわからなかった。

予選を確実に通過するのが目標だったため、問題1~5を確実にとれるように何度もソースや提出したファイルなどを確認した。
だから提出ミスなどはないと思う。

予選受ける前は「予選落ちはマジ笑えねぇ怖すぎ」と思っていたけどどうやらとおりそうなので安心する。

Youtubeで若干音楽を聞く。

競技時間終了。

twitterをすぐ見る。

ボーダー6完とかいうハラスメント発言に絶望。

以上です。


終わりに。
本選はがんばるし・・・