nyu 的AI课的调度问题

来源:互联网 发布:mac 安装mysql详解 编辑:程序博客网 时间:2024/06/05 21:05

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;}
0 0
原创粉丝点击