nyu 的AI课的调度问题

nyu 的AI课的课后习题
http://cs.nyu.edu/courses/spring12/CSCI-GA.2560-001/prog1.html
题目的大意是输入n个task 每个task都有time(完成时间) value(完成产生的价值) task可能会有先驱 打个比方就是 要先完成task1 才能去进行task2
给定一个targetvalue 和deadline(最后完成时间) 找到一种在deadline时间之前完成的 并且总价值达到targetvalue的解法

首先因为有先驱所以就要进行拓扑排序 。产生一个 topologyResult[]数组
来存储拓扑排序的结果。 然后就对拓扑排序的结果进行BFS , 用state
结构体来存储当前的状态。
state.selected[]:当前状态执行了那些点
state.totalvalue:当前状态的总价值
state.totaltime : 当前状态所用的总时间
state.currentdepth:当前状态 搜索到了topologyResult[]中的点的下标

首先进行BFS 取出队列首部的状态,对topologyResult[]中的每个点进行两种操作 尝试添加该点(
(1).总的time 没有达到了deadline 把这个状态加入队列的尾部 ,、
(2).总的time没有达到deadline 放弃这个状态) 将没有添加该点的状态加入队列的尾部 直到找到 达到targetvalue的状态
在没有找到targetvalue的情况下 队列的长度达到了queueMaxSize就进行 迭代深度优先搜索 在迭代深度优先搜索(IDDFS)中也是同样的
尝试添加该点 (1.总的time没有达到deadline 递归调用深度优先搜索 2.总的time达到了deadline 则不进行递归调用 )然后在没有添加该点的状态下进行递归调用!

#include <stdio.h>
#include <vector>
#include <map>
#include <queue>
using namespace std;

int taskNum;
int targetValue;
int deadline;
int queueMaxSize;

 struct State {
    bool * selected;
    int totalValue;
    int totalTime;
    int currentDepth;//当前搜索的状态处于哪一层
    State(State&a)
    {
        selected = new bool[taskNum];
        for (int i = 0; i < taskNum; i++)
        {
            selected[i] = a.selected[i];
        }
        totalValue = a.totalValue;
        totalTime = a.totalTime;
        currentDepth = a.currentDepth;
    }
    State()
    {
        selected = new bool[taskNum];
        memset(selected, false, sizeof(selected));
        totalValue = 0;
        totalTime = 0;
        currentDepth = -1;
    }
    State &operator=(const State &a)
    {
        for (int i = 0; i < taskNum; i++)
        {
            selected[i] = a.selected[i];
        }
        totalValue = a.totalValue;
        totalTime = a.totalTime;
        currentDepth = a.currentDepth;
    }
} ;

typedef struct {
    int time;
    int value;
} Node;

//记录某点的前序结点(即在执行该任务前必须完成的任务)
map<int, vector<int> *> nodesPre;
int ** edges;
Node * nodes;
int * topologyResult;//拓扑排序的结果数组,记录状态树每一层对应的点的标号
int * nodeToTopNode;
queue<int> q;//用于拓扑排序
queue<State> stateQ;//用于状态空间搜索的队列
State resState;//搜索到的结果状态
bool hasResult;

void initialState(State &state) {
    state.selected = new bool[taskNum];//对应tipologyResult中的元素有没有bfs过
    memset(state.selected, false, sizeof(state.selected));
    state.currentDepth = -1;
    state.totalTime = 0;
    state.totalValue = 0;
}

State copyState(State &state) {
    State newState;
    newState.selected = new bool[taskNum];
    for (int i = 0; i < taskNum; i++) {
        newState.selected[i] = state.selected[i];
    }
    newState.currentDepth = state.currentDepth;
    newState.totalTime = state.totalTime;
    newState.totalValue = state.totalValue;
    return newState;
}

bool checkPreNode(bool * selected, int nodeID) {
    vector<int> * v = nodesPre[nodeID];//得到nodeID节点对应的前驱节点
    if (v == NULL) {//当没有前驱节点时 说明前驱节点都完成
        return true;
    }
    vector<int>::iterator it = v->begin();
    for (; it != v->end(); it++) {//遍历该点所有的前序结点,有任何一个结点没有选择都返回false
                                  //nodeToTopNode映射数组填入原始标号,可以映射成拓扑排序结果中的下标
                                  //看拓扑排序中的下标是否已经被执行 
        if (selected[nodeToTopNode[*it]] == false) return false;
    }
    return true;
}

bool BFS() {
    State root;//初始状态空间树的搜索起点,即根节点
    initialState(root);
    stateQ.push(root);
    hasResult = false;
    while (!stateQ.empty()) {
        if (stateQ.size() == queueMaxSize) {
            //当该层结点可以选择时,就会压入两个状态,弹出一个状态,因此状态队列会越来越大
            //达到最大队列限制后跳出BFS,开始进行迭代深度优先搜索IDS
            break;
        }
        State state = stateQ.front();
        stateQ.pop();
        State tempSubState =state;
        if (tempSubState.currentDepth == taskNum - 1) {
            continue;
        }
        tempSubState.currentDepth++;
        int nodeID = topologyResult[tempSubState.currentDepth];
        //下面检查该点之前的结点是否都已经选择,且累计的value和time是否满足要求
        if (checkPreNode(tempSubState.selected, nodeID) == true) {
            Node tempNode = nodes[nodeID];
            tempSubState.selected[tempSubState.currentDepth] = true;
            tempSubState.totalTime += tempNode.time;
            tempSubState.totalValue += tempNode.value;
            if (tempSubState.totalTime <= deadline) {
                stateQ.push(tempSubState);
                if (tempSubState.totalValue >= targetValue) {
                    hasResult = true;
                    resState = copyState(tempSubState);
                    break;
                }
            }
        }
        //如果当前层结点可以选(没有出现未选的前序结点),就一共压入了两个状态入队列(选和不选);
        //否则就压入一个状态即不选改层结点的状态
        State tempSubState2 = copyState(state);
        tempSubState2.currentDepth++;
        tempSubState2.selected[tempSubState2.currentDepth] = false;
        stateQ.push(tempSubState2);
    }
    return hasResult;
}

bool DFS(int depth, State state) {//最大深度为depth,起始结点对应的状态state
    state.currentDepth++;//找到当前要判断的点在拓扑排序下标
    int nodeID = topologyResult[state.currentDepth];//找到是哪个点
    if (checkPreNode(state.selected, nodeID) == true) {//如果前驱都执行了
        Node node = nodes[nodeID];
        /* 尝试添加这个点 */
        state.selected[state.currentDepth] = true;
        state.totalValue += node.value;
        state.totalTime += node.time;

        /* 判断总的时间是否超时 */
        if (state.totalTime <= deadline) {
            if (state.totalValue >= targetValue) {//判断是否达到了总的价值
                resState = copyState(state);
                return true;
            }
            if (depth != 1) {//没有找到结果 添加该点后继续搜索拓扑排序后的下个点
                if (DFS(depth - 1, state)) {
                    return true;
                }
            }
        }
        //这里是不能选改层结点对应的递归 0 ,要先把该结点拿出来
        state.totalValue -= node.value;
        state.totalTime -= node.time;
    }

    /* 无论在添加currentDepth点后是否满足deadline 都在不添加currentDepth点后进行搜索currentDepth+1的深度 */
    state.selected[state.currentDepth] = false;
    if (depth != 1) {
        if (DFS(depth - 1, state)) {
            return true;
        }
    }
    return false;
}

bool IDS() {
    while (!stateQ.empty()) {
        State tempstate = stateQ.front();
        stateQ.pop();
        for (int i = 1; i <= taskNum - (tempstate.currentDepth + 1); i++) {//i为最大的搜索深度
            if (DFS(i, tempstate)) return true;
        }
    }
    return false;
}


bool findNoInDegreeNode(int i) {
    bool hashInDegree = false;
    for (int j = 0; j < taskNum; j++) {
        if (edges[j][i]) hashInDegree = true;
    }
    return hashInDegree;
}

void topologySort() {
    for (int i = 0; i < taskNum; i++) {
        if (findNoInDegreeNode(i) == false) q.push(i);
    }
    int j, count = 0;
    while (!q.empty()) {
        j = q.front();
        q.pop();
        topologyResult[count] = j;
        count++;
        for (int k = 0; k < taskNum; k++) {
            if (edges[j][k]) {
                edges[j][k] = 0;
                if (findNoInDegreeNode(k) == false)
                    q.push(k);
            }
        }
    }
    printf("拓扑排序结果为");
    for (int m = 0; m < taskNum; m++) {
        nodeToTopNode[topologyResult[m]] = m;//填入原始标号,可以映射成拓扑排序后的新标号
        printf("%d ", topologyResult[m]);
    }
}

void input() {
    scanf("%d%d%d%d", &taskNum, &targetValue, &deadline, &queueMaxSize);
    nodes = new Node[taskNum];
    edges = new int*[taskNum];
    topologyResult = new int[taskNum];
    nodeToTopNode = new int[taskNum];
    for (int j = 0; j < taskNum; j++) {
        edges[j] = new int[taskNum];
        for (int k = 0; k < taskNum; k++) {
            edges[j][k] = 0;
        }
    }

    int tempNum, preNode, lastNode;
    for (int i = 0; i < taskNum; i++) {
        scanf("%d%d%d", &tempNum, &nodes[i].value, &nodes[i].time);
    }
    while (true) {
        scanf("%d", &preNode);
        if (preNode == -1) break;
        scanf("%d", &lastNode);
        edges[preNode][lastNode] = 1;
        vector<int> * v = nodesPre[lastNode];//v指向lastNode对应的vector容器
        if (v == NULL) {
            v = new vector<int>;
            nodesPre[lastNode] = v;
        }
        v->push_back(preNode);
    }
}

void output() {
    printf("求得的解为:[");
    for (int i = 0; i<taskNum; i++) {
        if (resState.selected[i] == 1) {//注意结果state中第四项没有赋值,也是非零数
            printf(" %d ", topologyResult[i]);
        }
    }
    printf("] %d %d\n", resState.totalValue, resState.totalTime);
}

int main() {
    input();
    topologySort();
    if (!BFS() && !IDS()) {
        printf("no solutions");
    }
    else output();
    return 0;
}

你可能感兴趣的:(nyu 的AI课的调度问题)