1599 Station Balance

127 篇文章 0 订阅
22 篇文章 0 订阅

/*

状态压缩,比特运算

五进制表示spe的状态, 三进制表示当前cham的状态

然后直接DFS即可

*/

#include <iostream>
#include <cmath>
#define MAX_CH 5
#define MAX_SP 10

using namespace std;

int chamNum, speNum;
int spes[MAX_SP + 1];
int exp3[MAX_CH + 1];
int exp5[MAX_SP + 1];

double minIMB;
double average;
double countv[MAX_CH + 1];
int assignID[MAX_CH + 1][MAX_SP + 1];
int tempAssignID[MAX_CH + 1][MAX_SP + 1];
int minAssign;

int get3(int assgin, int p)
{
    return (assgin % exp3[p + 1]) / exp3[p];
}
int set3(int assign, int p, int num)
{
    int cur = get3(assign, p) * exp3[p];
    return assign - cur + num * exp3[p];
}
int get5(int assign, int p)
{
    return (assign % exp5[p + 1]) / exp5[p];
}
int set5(int assign, int p, int chamID)
{
    int cur = get5(assign, p) * exp5[p];
    return assign - cur + chamID * exp5[p];
}

void dfs(int speState, int chamState, int curSpe)
{
    //printf("->%d/n", speState);
    if(curSpe == speNum)
    {
        int p;
        double curIMB = 0;
        
        for(p = 0; p < chamNum; p++)
        {
            countv[p] = 0;
            tempAssignID[p][0] = 0;
        }
        for(p = 0; p < speNum; p++)
        {
            int chamID = get5(speState, p);
            countv[chamID] += spes[p];
            tempAssignID[chamID][0]++;
            tempAssignID[chamID][tempAssignID[chamID][0]] = spes[p];
        }
        for(p = 0; p < chamNum; p++)
            curIMB += fabs(countv[p] - average);
        if(curIMB < minIMB)
        {
            minIMB = curIMB;
            minAssign = speState;
            for(p = 0; p < chamNum; p++)
                for(int t = 0; t <= tempAssignID[p][0]; t++)
                    assignID[p][t] = tempAssignID[p][t];
        }
        return;
    }
    int c, s, newSpeState, newChamState;
    for(s = 0; s < chamNum; s++)
    {
        int curNum = get3(chamState, s);
        if(curNum == 2) continue;
        newSpeState = set5(speState, curSpe, s);
        newChamState = set3(chamState, s, curNum + 1);
        dfs(newSpeState, newChamState, curSpe + 1);
    }
}

void printRes(int s)
{
    int p, c;
    printf("Set #%d/n", s);
    for(p = 0; p < chamNum; p++)
    {
        printf(" %d:", p);
        for(c = 1; c <= assignID[p][0]; c++)
            printf(" %d", assignID[p][c]);
        printf("/n");
    }
    printf("IMBALANCE %.5f/n", minIMB);
}
int main()
{
    int i, c = 0;
    exp5[0] = 1, exp3[0] = 1;
    for(i = 1; i <= MAX_CH; i++)
        exp3[i] = exp3[i - 1] * 3;
    for(i = 1; i <= MAX_SP; i++)
        exp5[i] = exp5[i - 1] * 5;
    while(scanf("%d%d", &chamNum, &speNum) != EOF)
    {
        c++;
        minIMB = INT_MAX;
        average = 0;
        for(i = 0; i < speNum; i++)
        {
            scanf("%d", &spes[i]);
            average += spes[i];
        }
        average = average / chamNum;
        dfs(0, 0, 0);
        printRes(c);
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值