Cod sursa(job #2343702)

Utilizator Tiberiu02Tiberiu Musat Tiberiu02 Data 14 februarie 2019 11:15:00
Problema A+B Scor 0
Compilator cpp-64 Status done
Runda Lista lui wefgef Marime 5.46 kb
#include <iostream>
#include <fstream>
#include <iomanip>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <vector>

using namespace std;

const int N = 10;
const int L = 3;
const int E = 100;
double f[L][N][N][N];
double e[E][L][N][N][N];
/// f[l][a][b][x] = the probability for picking x, given that the ball
/// is a dinstance l from the player's base, the player has a banace of
/// a and the enemy has a balance of b

/// Num. data points = L * N^3 = 3000

const int EPOCH = 1;
const int NUM_ATTEMPTS = 1000000000;
const double lr = 1.1;

int draw_random(double *f, int n) {
    double p = 1.0 * rand() / RAND_MAX;
    for (int i = 1; i < n; i++) {
        if (f[i] > p)
            return i;
        p -= f[i];
    }
    return n - 1;
}

void normalize(double *f, int n) {
    double sum = 0;
    for (int i = 0; i < n; i++)
        sum += f[i];
    for (int i = 1; i < n; i++)
        f[i] = max(f[i] / sum, 0.001);
}

double F(double f[L][N][N][N], double g[L][N][N][N]) {
    double ans = 0, ans2 = 0, dr = 0;
    double p[L][N][N] = {};
    p[1][N - 1][N - 1] = 1.0;
    for (int att = 4; att > 0; att--) {
        for (int a = N - 1; a >= 0; a--)
            for (int b = N - 1; b >= 0; b--) {
                if (!a && !b) dr += p[1][a][b];
                for (int i = 1; i <= a; i++)
                    for (int j = 1; j <= b; j++) {
                        double P = p[1][a][b] * f[1][a][b][i] * g[1][b][a][j];// / (1 - f[1][a][b][0] * g[1][b][a][0]);
                        if (i > j) {
                            p[2][a - i][b - j] += P;
                        } else if (j > i) {
                            p[0][a - i][b - j] += P;
                        } else {
                            p[1][a - i][b - j] += P;
                        }
                    }
                p[1][a][b] = 0;
            }

        for (int a = N - 1; a >= 0; a--)
            for (int b = N - 1; b >= 0; b--) {
                if (!a && !b) dr += p[0][a][b];
                for (int i = 1; i <= a; i++)
                    for (int j = 1; j <= b; j++) {
                        double P = p[0][a][b] * f[0][a][b][i] * g[2][b][a][j];// / (1 - f[0][a][b][0] * g[2][b][a][0]);
                        if (i > j) {
                            p[1][a - i][b - j] += P;
                        } else if (j > i) {
                            ans2 += P;
                        } else {
                            p[0][a - i][b - j] += P;
                        }
                    }
                p[0][a][b] = 0;
            }

        for (int a = N - 1; a >= 0; a--)
            for (int b = N - 1; b >= 0; b--) {
                if (!a && !b) dr += p[2][a][b];
                for (int i = 1; i <= a; i++)
                    for (int j = 1; j <= b; j++) {
                        double P = p[2][a][b] * f[2][a][b][i] * g[0][b][a][j];// / (1 - f[2][a][b][0] * g[0][b][a][0]);
                        if (i > j) {
                            ans += P;
                        } else if (j > i) {
                            p[1][a - i][b - j] += P;
                        } else {
                            p[2][a - i][b - j] += P;
                        }
                    }
                p[2][a][b] = 0;
            }

    }
    return ans / (ans + ans2);
}

double eval() {
    double score = 0;
    for (int i = 0; i < E; i++)
        score += F(f, e[i]);
    return score / E;
}

int main() {
    srand(time(NULL));
    for (int l = 0; l < L; l++)
        for (int a = 0; a < N; a++)
            for (int b = 0; b < N; b++)
                for (int x = 1; x <= a; x++)
                    f[l][a][b][x] = 1.0 / a;

    for (int i = 0; i < E; i++)
        for (int l = 0; l < L; l++)
            for (int a = 0; a < N; a++)
                for (int b = 0; b < N; b++) {
                    for (int x = 1; x <= a; x++)
                        e[i][l][a][b][x] = pow(1.0 * rand() / RAND_MAX, 3);
                    normalize(e[i][l][a][b], a + 1);
                }

    double score = eval();

    for (int attempt = 1; attempt <= NUM_ATTEMPTS; attempt++) {

        for (int l = 0; l < L; l++)
            for (int a = 0; a < N; a++) {
                double c[N];
                for (int b = 0; b < N; b++) {
                    for (int x = 0; x <= a; x++) {
                        memcpy(c, f[l][a][b], sizeof(c));
                        f[l][a][b][x] *= lr;
                        normalize(f[l][a][b], a + 1);
                        double ev = eval();
                        if (ev <= score)
                            memcpy(f[l][a][b], c, sizeof(c));
                        else
                            score = ev;
                    }
                }
            }

        if (attempt % EPOCH == 0) {
            for (int i = 0; i < N; i++)
                cout << i << ": " << fixed << setprecision(2) << f[1][N - 1][N - 1][i] << endl;
            cout << endl;
            cout << endl << "Win rate: " << score;
            cout << endl << endl;

            ofstream out1("f1.txt");
            for (int l = 0; l < L; l++) {
                out1 << "L=" << l << '\n' << '\n';
                for (int a = 0; a < N; a++)
                    for (int b = 0; b < N; b++) {
                        out1 << "a=" << a << ", b=" << b << '\n';
                        for (int x = 1; x <= a; x++)
                            out1 << x << ": " << (int)(f[l][a][b][x] * 100) << "%\n";
                        out1 << '\n';
                    }
                out1 << '\n';
            }
        }
    }


    return 0;
}