結果
| 問題 |
No.545 ママの大事な二人の子供
|
| コンテスト | |
| ユーザー |
asugen0402
|
| 提出日時 | 2019-04-16 16:51:53 |
| 言語 | C (gcc 13.3.0) |
| 結果 |
AC
|
| 実行時間 | 18 ms / 2,000 ms |
| コード長 | 5,952 bytes |
| コンパイル時間 | 331 ms |
| コンパイル使用メモリ | 32,384 KB |
| 実行使用メモリ | 6,944 KB |
| 最終ジャッジ日時 | 2024-09-22 08:19:12 |
| 合計ジャッジ時間 | 1,173 ms |
|
ジャッジサーバーID (参考情報) |
judge4 / judge5 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| other | AC * 32 |
ソースコード
#include <float.h>
#include <limits.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
// 内部定数
#define D_ITM_MAX 32 // 最大品物数
#define D_PTN_CNT 2 // パターン種類数
#define D_PTN_1ST 0 // パターン - 前半
#define D_PTN_2ND 1 // パターン - 後半
#define D_PTN_MAX 70000 // 最大パターン数
// 内部構造体 - 品物情報
typedef struct Itm {
long long mlA, mlB; // A, B
} Itm;
// 内部変数
static FILE *szpFpI; // 入力
static Itm sz1Itm[D_ITM_MAX]; // 品物
static int siICnt; // 品物数
static long long sl2Ptn[D_PTN_CNT][D_PTN_MAX]; // パターン
static int si1PCnt[D_PTN_CNT]; // パターン数
// 内部変数 - テスト用
#ifdef D_TEST
static int siRes;
static FILE *szpFpA;
static int siTNo;
#endif
// 出力
int
fOut(
char *pcpLine // <I> 1行
)
{
char lc1Buf[1024];
#ifdef D_TEST
fgets(lc1Buf, sizeof(lc1Buf), szpFpA);
if (strcmp(lc1Buf, pcpLine)) {
siRes = -1;
}
#else
printf("%s", pcpLine);
#endif
return 0;
}
// パターン - セット
int
fSetPtn(
int piKind // <I> 種類
, int piNNo // <I> 現在位置 0~
, int piENo // <I> 終了位置 0~
, long long plA // <I> A合計
, long long plB // <I> B合計
)
{
// 選択中
if (piNNo <= piENo) {
// A
fSetPtn(piKind, piNNo + 1, piENo, plA + sz1Itm[piNNo].mlA, plB);
// B
fSetPtn(piKind, piNNo + 1, piENo, plA, plB + sz1Itm[piNNo].mlB);
return 0;
}
// パターン - セット
sl2Ptn[piKind][si1PCnt[piKind]] = plA - plB;
si1PCnt[piKind]++;
return 0;
}
// ソート関数 - long long昇順
int
fSortFnc(
const void *pzpVal1 // <I> 値1
, const void *pzpVal2 // <I> 値2
)
{
long long *llpVal1 = (long long *)pzpVal1;
long long *llpVal2 = (long long *)pzpVal2;
// long long昇順
if (*llpVal1 > *llpVal2) {
return 1;
}
else if (*llpVal1 < *llpVal2) {
return -1;
}
return 0;
}
// パターン後半 - 重複カット
int
fCutDpl(
long long *plpArray // <I> 配列
, int piACnt // <I> 配列数
)
{
int i;
int liTo = 1;
for (i = 1; i < piACnt; i++) {
if (plpArray[i] != plpArray[liTo - 1]) {
plpArray[liTo] = plpArray[i];
liTo++;
}
}
return 0;
}
// パターン後半 - 検索+前後
// 戻り値:[>=0]配列番号 [-1]なし
int
fBSrhPN(
long long plVal // <I> 値
, int *pipPNo // <O> [>=0]1つ前の値の配列番号 [-1]なし
, int *pipNNo // <O> [>=0]1つ後の値の配列番号 [siACnt]なし
)
{
// 初期範囲
int liSNo = 0;
int liENo = si1PCnt[D_PTN_2ND] - 1;
// 検索
while (1) {
// 中間位置
int liMNo = (liSNo + liENo) / 2;
// 一致チェック
if (plVal == sl2Ptn[D_PTN_2ND][liMNo]) {
*pipPNo = liMNo - 1;
*pipNNo = liMNo + 1;
return liMNo;
}
// 範囲を絞る
if (plVal < sl2Ptn[D_PTN_2ND][liMNo]) { // 左側へ
if (liSNo < liMNo) { // 範囲あり
liENo = liMNo - 1;
}
else { // 範囲なし
*pipPNo = liMNo - 1;
*pipNNo = liMNo;
return -1;
}
}
else { // 右側へ
if (liENo > liMNo) { // 範囲あり
liSNo = liMNo + 1;
}
else { // 範囲なし
*pipPNo = liMNo;
*pipNNo = liMNo + 1;
return -1;
}
}
}
return -1;
}
// 差異 - 取得
long long
fGetDF(
int piNo1 // <I> 位置1 0~
, int piNo2 // <I> 位置2 0~
)
{
return llabs(sl2Ptn[0][piNo1] + sl2Ptn[1][piNo2]);
}
// 実行メイン
long long
fMain(
)
{
int i;
char lc1Buf[1024];
// 品物数 - 取得
fgets(lc1Buf, sizeof(lc1Buf), szpFpI);
sscanf(lc1Buf, "%d", &siICnt);
// 品物 - 取得
for (i = 0; i < siICnt; i++) {
fgets(lc1Buf, sizeof(lc1Buf), szpFpI);
sscanf(lc1Buf, "%lld%lld", &sz1Itm[i].mlA, &sz1Itm[i].mlB);
}
// 品物1つ
if (siICnt == 1) {
if (sz1Itm[0].mlA < sz1Itm[0].mlB) {
return sz1Itm[0].mlA;
}
else {
return sz1Itm[0].mlB;
}
}
// パターン - セット
int liNo = siICnt / 2 - 1;
fSetPtn(0, 0, liNo, 0, 0);
fSetPtn(1, liNo + 1, siICnt - 1, 0, 0);
// パターン後半 - ソート
qsort(sl2Ptn[D_PTN_2ND], si1PCnt[D_PTN_2ND], sizeof(long long), fSortFnc);
// パターン後半 - 重複カット
fCutDpl(sl2Ptn[D_PTN_2ND], si1PCnt[D_PTN_2ND]);
// 最小値 - 取得
long long llMin = LLONG_MAX;
for (i = 0; i < si1PCnt[D_PTN_1ST]; i++) {
// 現在パターンでの最小値 - 取得
int liNo, liPNo, liNNo;
liNo = fBSrhPN(-sl2Ptn[D_PTN_1ST][i], &liPNo, &liNNo);
if (liNo >= 0) {
llMin = 0;
break;
}
// 前
if (liPNo >= 0) {
long long llVal = fGetDF(i, liPNo);
if (llMin > llVal) {
llMin = llVal;
}
}
// 後
if (liNNo < si1PCnt[D_PTN_2ND]) {
long long llVal = fGetDF(i, liNNo);
if (llMin > llVal) {
llMin = llVal;
}
}
}
return llMin;
}
// 1回実行
int
fOne(
)
{
long long llRet;
char lc1Buf[1024];
// データ - 初期化
memset(si1PCnt, 0, sizeof(si1PCnt)); // パターン数
// 入力 - セット
#ifdef D_TEST
sprintf(lc1Buf, ".\\Test\\T%d.txt", siTNo);
szpFpI = fopen(lc1Buf, "r");
sprintf(lc1Buf, ".\\Test\\A%d.txt", siTNo);
szpFpA = fopen(lc1Buf, "r");
siRes = 0;
#else
szpFpI = stdin;
#endif
// 実行メイン
llRet = fMain();
// 出力
sprintf(lc1Buf, "%lld\n", llRet);
fOut(lc1Buf);
// 残データ有無
#ifdef D_TEST
lc1Buf[0] = '\0';
fgets(lc1Buf, sizeof(lc1Buf), szpFpA);
if (strcmp(lc1Buf, "")) {
siRes = -1;
}
#endif
// テストファイルクローズ
#ifdef D_TEST
fclose(szpFpI);
fclose(szpFpA);
#endif
// テスト結果
#ifdef D_TEST
if (siRes == 0) {
printf("OK %d\n", siTNo);
}
else {
printf("NG %d\n", siTNo);
}
#endif
return 0;
}
// プログラム開始
int
main()
{
#ifdef D_TEST
int i;
for (i = D_TEST_SNO; i <= D_TEST_ENO; i++) {
siTNo = i;
fOne();
}
#else
fOne();
#endif
return 0;
}
asugen0402