Last active
May 7, 2017 07:53
-
-
Save buyoh/c1d44bb2dd7801e1a99e9b6b8bb9a79d to your computer and use it in GitHub Desktop.
動作が不安定.verify?(http://yukicoder.me/submissions/172535)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma GCC optimize ("O3") | |
#pragma GCC target ("avx") | |
#include "bits/stdc++.h" // define macro "/D__MAI" | |
using namespace std; | |
typedef unsigned int uint; | |
typedef long long int ll; | |
typedef unsigned long long int ull; | |
#define debugv(v) printf("L%d %s => ",__LINE__,#v);for(auto e:v){cout<<e<<" ";}cout<<endl; | |
#define debugm(m) printf("L%d %s is..\n",__LINE__,#m);for(auto v:m){for(auto e:v){cout<<e<<" ";}cout<<endl;} | |
#define debuga(m,w) printf("L%d %s is => ",__LINE__,#m);for(int x=0;x<(w);x++){cout<<(m)[x]<<" ";}cout<<endl; | |
#define debugaa(m,w,h) printf("L%d %s is..\n",__LINE__,#m);for(int y=0;y<(h);y++){for(int x=0;x<(w);x++){cout<<(m)[x][y]<<" ";}cout<<endl;} | |
#define debugaar(m,w,h) printf("L%d %s is..\n",__LINE__,#m);for(int y=0;y<(h);y++){for(int x=0;x<(w);x++){cout<<(m)[y][x]<<" ";}cout<<endl;} | |
#define ALL(v) (v).begin(),(v).end() | |
#define repeat(l) for(auto cnt=0;cnt<(l);++cnt) | |
#define upto(l,r) for(auto cnt=l;cnt<=r;++cnt) | |
#define downto(r,l) for(auti cnt=r;cnt>=l;--cnt) | |
#define BIGINT 0x7FFFFFFF | |
#define MD 1000000007ll | |
#define PI 3.1415926535897932384626433832795 | |
template<typename T1, typename T2> | |
ostream& operator <<(ostream &o, const pair<T1, T2> p) { o << "(" << p.first << ":" << p.second << ")"; return o; } | |
#define TIME chrono::system_clock::now() | |
#define MILLISEC(t) (chrono::duration_cast<chrono::milliseconds>(t).count()) | |
namespace { | |
std::chrono::system_clock::time_point ttt; | |
void tic() { ttt = TIME; } | |
void toc() { fprintf(stderr, "TIME : %lldms\n", MILLISEC(TIME - ttt)); } | |
std::chrono::system_clock::time_point tle = TIME; | |
#ifdef __MAI | |
void safe_tle(int msec) { assert(MILLISEC(TIME - tle) < msec); } | |
#else | |
#define safe_tle(k) ; | |
#endif | |
} | |
#ifdef __MAI //_getchar_nolock | |
#define getchar_unlocked getchar | |
#endif | |
namespace { | |
class MaiScanner { | |
public: | |
template<typename T> | |
void input_integer(T& var) { | |
var = 0; | |
T sign = 1; | |
int cc = getchar_unlocked(); | |
for (; cc<'0' || '9'<cc; cc = getchar_unlocked()) | |
if (cc == '-') sign = -1; | |
for (; '0' <= cc&&cc <= '9'; cc = getchar_unlocked()) | |
var = (var << 3) + (var << 1) + cc - '0'; | |
var = var*sign; | |
} | |
inline int c() { return getchar_unlocked(); } | |
inline MaiScanner& operator>>(int& var) { | |
input_integer<int>(var); | |
return *this; | |
} | |
inline MaiScanner& operator>>(long long& var) { | |
input_integer<long long>(var); | |
return *this; | |
} | |
}; | |
} | |
MaiScanner scanner; | |
typedef int boolean; | |
class EasyLP { | |
public: | |
const int dimension; | |
vector<vector<double>> equation; | |
vector<double> offset; | |
vector<double> objective; | |
double objective_c; | |
EasyLP(int n) :dimension(n), objective(n) { | |
} | |
// void appendEquation() {} | |
// void setObjective() {} | |
double maximize() { | |
while (true) { | |
//printTableau(); | |
// 目的関数の値を増加させることができる変数を探す | |
int idx = 0; | |
{ | |
double val = objective[0]; | |
for (int i = 1; i < dimension; ++i) { | |
if (val > objective[i]) { | |
val = objective[i]; | |
idx = i; | |
} | |
} | |
// 無いなら最適解が得られた | |
if (val >= 0) break; | |
} | |
// どの程度まで増やせば良いだろうか | |
int target = -1; | |
{ | |
double val, lim = 0; | |
for (int i = 0; i < equation.size(); ++i) { | |
if (equation[i][idx] == 0) continue; // 0除算防止 | |
val = offset[i] / equation[i][idx]; | |
if ((target == -1 || val < lim)) { | |
lim = val; | |
target = i; | |
} | |
} | |
}; | |
if (target == -1) break; | |
// 参考 http://www.mk-mode.com/octopress/2014/02/21/cpp-linear-programming-by-simplex/ | |
// この実装だとうまく出来ないケースが存在するかもしれない | |
{ | |
// ピボット係数 | |
double p = equation[target][idx]; | |
// ピボット係数を p で除算 | |
for (double& e : equation[target]) | |
e /= p; | |
offset[target] /= p; | |
// ピボット列の掃き出し | |
for (int i = 0; i < equation.size(); ++i) { | |
if (i == target) continue; | |
double d = equation[i][idx]; | |
for (int j = 0; j < dimension; j++){ | |
if (j!=idx) | |
equation[i][j] -= d * equation[target][j]; | |
else | |
equation[i][j] = 0; | |
} | |
offset[i] -= d * offset[target]; | |
} | |
{ | |
double d = objective[idx]; | |
for (int j = 0; j < dimension; j++){ | |
if (j!=idx) | |
objective[j] -= d * equation[target][j]; | |
else | |
objective[j] = 0; | |
} | |
objective_c += d * offset[target]; | |
} | |
} | |
} | |
return -objective_c; | |
} | |
void printTableau() { | |
repeat(equation.size()) { | |
for (double a : equation[cnt]) { | |
printf(" %7.2f", a); | |
} | |
printf(" | %7.2f\n", offset[cnt]); | |
} | |
repeat(equation.size() + 1) { printf("---------"); } | |
printf("\n"); | |
for (double a : objective) { | |
printf(" %7.2f", a); | |
} | |
printf(" %7.2f\n#####\n",objective_c); | |
} | |
}; | |
int main() { | |
EasyLP lp(5); | |
lp.equation.push_back({ -1.0, 1.0, 1.0, 0.0, 0.0 }); lp.offset.push_back(1.0); | |
lp.equation.push_back({ 1.0, 0.0, 0.0, 1.0, 0.0 }); lp.offset.push_back(3.0); | |
lp.equation.push_back({ 0.0, 1.0, 0.0, 0.0, 1.0 }); lp.offset.push_back(2.0); | |
lp.objective = { 1.0, 1.0, 0.0, 0.0, 0.0 }; lp.objective_c = 0.0; | |
double result = lp.maximize(); | |
printf("result: %7.2f\n", result); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment