読者です 読者をやめる 読者になる 読者になる

amori's blog

よろず技術系と趣味関係の雑記です

Paiza ハッカソン「火消し霧島」その2

続き

さてテーブル全体の初期化が原因でくまなく0.01秒損していたのだから、ケース7ではおそらくほぼ最大設定の条件になっているはずなので、この初期化で0.01秒損していることになる。

もういっそのことテーブルの初期化を止めてstaticで設定される0を初期値としてしまおう。

ただ原理的には0行と0列についてのみ「0」が「コスト=0」という意味をもってしまっているので、この行と列についてのみ処理を別にしてしまえばいい。

ver.0.2での変更は、初期化処理の省略と

//初期値変更により0列だけ特殊処理ver.0.2
  AssignIfGreater(cost_tbl[i][smp],cost_tbl[i-1][0]+scost);
  for( j = 1 ; j <= total_manpower ; j++ ){ // j=0 -> j=1 , ver.0.2

この一行追加とjの開始を1からにしただけ。

その結果が、

amoriさんの採点結果[100点] 完璧ぃぃ!|paizaオンラインハッカソンLite

うん、読み通りケース7が0.03秒になったわw

 

さらに

if( j+smp <= limit_manpower ) //ver.0.3
   AssignIfGreater(cost_tbl[i][j+smp],cost_tbl[i-1][j]+scost);

 のを追加して、条件を超えてしまった人員・コストの組み合わせをスキップして、

amoriさんの採点結果[100点] 完璧ぃぃ!|paizaオンラインハッカソンLite

ケース7が0.02秒

採点は100点だけど、まだSクラスということはケース6,7をそれぞれ0.01秒にすればSS,SSSということかな。

 

ここまでのソースは以下。

まだまだ無駄があるw

 

/* paiza Hackathon No.3 */
/* hk ver. 0.2 2014.08.10 */
/* by amori */
/*0.0 べたべた実装 */
/*0.1 初期化だけテーブル必要分のみ*/
/*0.2 いっそ初期化をやめる    */
/*0.3 条件超過の組み合わせをスキップ*/

#include<stdio.h>

// Parameter Declaration

#define AssignIfGreater(x,y) if( x < y ) x = y

#define MAX_MANPOWER 500000
#define MAX_SUBCON 50
#define MAX_STAFF_OF_SUBCON 10000
#define MAX_BUDGET 5000000

#define C_NIL 0 //static による初期化(ver. 0.2)
#define SC_MAN_POWER 0
#define SC_COST 1


//--------------------------------------------
int sconlist[MAX_SUBCON+1][2];

static int cost_tbl[MAX_SUBCON+1][MAX_MANPOWER+1];
int total_manpower;
int total_cost;
int limit_manpower;

int req_mp, n_subcon;
//--------------------------------------------

void init_table(void)
{
/* テーブル初期化廃止ver.0.2
int i,j;

for( i = 0 ; i <= n_subcon ; i++ ){ //MAX_SUBCONから必要分のみ初期化
for( j = 0 ; j <= total_manpower ; j++){ //MAX_MANPOWERから必要分のみ初期化
cost_tbl[i][j]= C_NIL;
}
}
*/
return;
}
/*---------------------------------------*/
main()
{
int i,j;

int smp,scost,m_cost;

 

// req_mp 必要な人員
scanf("%d",&req_mp);
// n_subcon 下請け会社数
scanf("%d ",&n_subcon);

// subcon 情報を読み込み
total_manpower = 0;
total_cost = 0;
for( i = 1 ; i <= n_subcon ; i++ ){
scanf("%d %d\n",&smp, &scost);
sconlist[i][SC_MAN_POWER]= smp;
sconlist[i][SC_COST]= scost;
total_manpower += smp;
total_cost += scost;

}
limit_manpower = total_manpower - req_mp;

init_table();
// ここから組合せ探索
// cost_tbl[0][0]=0; //設定不要 ver.0.2
for( i = 1; i <= n_subcon ; i++ ){
smp = sconlist[i][SC_MAN_POWER];
scost = sconlist[i][SC_COST];

//初期値変更により0列だけ特殊処理ver.0.2
AssignIfGreater(cost_tbl[i][smp],cost_tbl[i-1][0]+scost);
//limit_manpowerを超える条件は枝刈り ver.0.3
for( j = 1 ; j <= limit_manpower ; j++ ){ // j=0 -> j=1 ver.0.2
// total_manpower -> limit_manpower ver0.3
if( cost_tbl[i-1][j] != C_NIL){
AssignIfGreater(cost_tbl[i][j],cost_tbl[i-1][j]) ;
if( j+smp <= limit_manpower ) //ver.0.3
AssignIfGreater(cost_tbl[i][j+smp],cost_tbl[i-1][j]+scost);
}
}

}
m_cost=0;
for( j = 0; j<= limit_manpower ; j++){
if(cost_tbl[n_subcon][j] != C_NIL){
if( cost_tbl[n_subcon][j] > m_cost) m_cost=cost_tbl[n_subcon][j];
}
}
printf("%d\n", total_cost - m_cost);
return 0;
}