AtCoderのABC
次のABCの問題へ
前のABCの問題へ
ABC125-D Flipping Signs
C#のソース(DP)
using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
static string InputPattern = "InputX";
static List<string> GetInputList()
{
var WillReturn = new List<string>();
if (InputPattern == "Input1") {
WillReturn.Add("3");
WillReturn.Add("-10 5 -4");
//19
}
else if (InputPattern == "Input2") {
WillReturn.Add("5");
WillReturn.Add("10 -4 -8 -11 3");
//30
}
else if (InputPattern == "Input3") {
WillReturn.Add("11");
WillReturn.Add("-1000000000 1000000000 -1000000000 1000000000 -1000000000 0 1000000000 -1000000000 1000000000 -1000000000 1000000000");
//10000000000
}
else {
string wkStr;
while ((wkStr = Console.ReadLine()) != null) WillReturn.Add(wkStr);
}
return WillReturn;
}
static void Main()
{
List<string> InputList = GetInputList();
long[] AArr = InputList[1].Split(' ').Select(pX => long.Parse(pX)).ToArray();
long UB = AArr.GetUpperBound(0);
// 和の最大値[符号反転済みか]
long?[] PrevDP = new long?[2];
PrevDP[0] = AArr[0];
PrevDP[1] = -AArr[0];
for (long I = 1; I <= UB - 1; I++) {
long?[] CurrDP = new long?[2];
for (long J = 0; J <= 1; J++) {
if (PrevDP[J].HasValue == false) continue;
Action<long, long> SendAct = (pNewJ, pNewVal) =>
{
if (CurrDP[pNewJ].HasValue) {
if (CurrDP[pNewJ] >= pNewVal) {
return;
}
}
CurrDP[pNewJ] = pNewVal;
};
// 反転させない場合
SendAct(J, PrevDP[J].Value + AArr[I]);
// 反転する場合
long NewJ = (J + 1) % 2;
SendAct(NewJ, PrevDP[J].Value - AArr[I]);
}
PrevDP = CurrDP;
}
var AnswerKouho = new List<long>();
AnswerKouho.Add(PrevDP[0].Value + AArr[UB]);
AnswerKouho.Add(PrevDP[1].Value - AArr[UB]);
Console.WriteLine(AnswerKouho.Max());
}
}
C#のソース(不変量に着目)
using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
static string InputPattern = "InputX";
static List<string> GetInputList()
{
var WillReturn = new List<string>();
string wkStr;
while ((wkStr = Console.ReadLine()) != null) WillReturn.Add(wkStr);
return WillReturn;
}
static void Main()
{
List<string> InputList = GetInputList();
int[] AArr = InputList[1].Split(' ').Select(X => int.Parse(X)).ToArray();
// 負数の数
int MinusCnt = AArr.Count(X => X < 0);
// 絶対値の最小値
int MinABS = AArr.Min(X => Math.Abs(X));
long SumABS = 0;
Array.ForEach(AArr, X => SumABS += Math.Abs(X));
// 負数が偶数個の場合
if (MinusCnt % 2 == 0) {
Console.WriteLine(SumABS);
}
else { // 負数が奇数個の場合
Console.WriteLine(SumABS - MinABS * 2);
}
}
}
解説
和の最大値[符号反転済みか]
を更新するDPで解くことができますが、
マイナスの数の不変量に着目すると
mod 2 の世界で不変なので、
これを使って解くこともできます。