2012年12月16日日曜日

JOI予選

スパゲティパーティ

問1:国語、算数のページ数a,bと一日に進むページ数c,dからかかる日数をlから引いた答えを返す。
#include<iostream>
using namespace std;

int main(void){
  int l,a,b,c,d;
  cin >> l;
  cin >> a;
  cin >> b;
  cin >> c;
  cin >> d;
  int i = 0;
  while(a > c * i || b > d * i)
    i++;
  cout << l - i << endl;
  return 0;
}

なんか恐る恐るやってたら時間かかった。
単純に割って切り上げればいいだけなんだけど、わざわざループやってるから遅い。


問2:n人のプレイヤーがカードを出していって、かぶらなければ得点になるゲームを3回行う
#include<iostream>
#include<vector>
using namespace std;
int card[3][200];
int score[200];

int main(void){
  int n;
  cin >> n;
  for(int i = 0; i < n; i++)
    cin >> card[0][i] >> card[1][i] >> card[2][i];

  for(int i = 0; i < 3; i++)
    for(int j = 0; j < n; j++){
      if(card[i][j] == -1){
	//cout << i << "tes" << endl;
	continue;
      }
      bool flag = true;
      for(int k = j + 1; k < n; k++){
	if(card[i][k] == card[i][j]){
	  card[i][k] = -1;
	  flag = false;
	}
      }
      if(flag)
	score[j] += card[i][j];
    }
  for(int i = 0; i < n; i++)
    cout << score[i] << endl; //score[n]とかやってた
  return 0;
}

単に数えるだけ。かぶったら-1突っ込んどいた。

ここまでで(問題見る時間も含めて)1時間かかってます。
レッドブル飲んだらやたら調子悪くなった。

問3:見本の文字列とn個の入力を渡されて、入力された文字列から文字をいくつか消したとき、見本の文字列が等間隔に並んでいる入力の個数を返す。
#include<iostream>
#include<cstring>
using namespace std;

int main(void){
  //cout << "tes" << endl;
  int n, len;
  int ans = 0;
  char str[27], buf[103];
  char s[100][103];

  cin >> n;
  cin >> str;
  for(int i = 0; i < n; i++){
     cin >> buf;
     strcpy(s[i], buf);
  }


  len = strlen(str);

  for(int i = 0; i < n; i++){
    cout << 'i' << i << endl;
    bool flag = false;
    for(int j = 0; j < strlen(s[i]) - len + 1; j++){
      if(flag) break;

      if(s[i][j] == str[0]){
	for(int k = j + 1; k < strlen(s[i]) - len + 2; k++){

	  if(s[i][k] == str[1]){
	    int d = k - j;
	    bool f = true;

	    for(int l = 2; l < strlen(str); l++){
	      if(s[i][k + d * (l - 1)] != str[l])
		f = false;
	      break;
	    }

	    if(f){
	      ans++;
	      flag = true;
	      break;
	    }

	  }
	}
      }
    }
  }

  cout << ans << endl;
  return 0;
}
最後の最後にようやく書き終わったと思ったら何故か入力2で落ちたので入力1しか提出出来なかった。
原因は、入力のバッファとして使ってたbuf[103]がbuf[27]になってた。容量オーバー。
いらない処理してたり、len = strlen(str) ってやってるのに条件判定で strlen(str) をそのまま使ってるあたりひどい。

問4:気温がC1以上C2以下の時着られる派手さHの服N着とD日間の気温を渡されて、派手さの差の合計の最大値を返す問題
#include<iostream>
#define minc 0
#define maxc 1
#define hade 2
using namespace std;
int N[201][3] = {0};
int D[201] = {0};
int dp[201][200];

int main(void){
  for(int i = 0; i < 201; i++)
    for(int j = 0; j < 200; j++)
      dp[i][j] = -1;
  int n, d;
  cin >> d >> n;
  for(int i = 1; i <= d; i++)
    cin >> D[i];
  for(int i = 0; i < n; i++)
    cin >> N[i][minc] >> N[i][maxc] >> N[i][hade];

  for(int i = 0; i < n; i++)
    if(D[1] >= N[i][minc] && D[1] <= N[i][maxc])
      dp[1][i] = 0;


  for(int i = 2; i <= d; i++){

    for(int j = 0; j < n; j++){

      if(D[i] >= N[j][minc] && D[i] <= N[j][maxc]){

	int max = -1;

	for(int k = 0; k < n; k++){
	  if(dp[i - 1][k] != -1){
	    int temp = N[k][hade] - N[j][hade];
	    if(temp < 0) temp = temp * (-1);
	    if(max < temp + dp[i - 1][k]) max = temp + dp[i - 1][k];
	  }
	}
	if(max != -1)
	    dp[i][j] = max;
      }
    }
  }

  int max = 0;
  for(int i = 0; i < n; i++)
    if(max < dp[d][i])
      max = dp[d][i];
  cout << max << endl;
  return 0;
}
単純にDPするだけだと思う。dp[a][b]でa日目にbの服を着た場合の派手さの差の合計の最大値を格納していけばどうにかなる。

感想
やっぱり経験不足のせいだと思うけど、(今回に限らず)コードがスパゲティ過ぎるのをどうにかしたいと思った。
あと今回普通に4完いけたはずなので、もっと落ち着いて解ければよかった。

とりあえず今回で競技プログラミングは休止して受験勉強に入ります。

0 件のコメント:

コメントを投稿