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;}
- nyu 的AI课的调度问题
- NYU AI作业习题-活动安排问题 BFS+DFS Iterative deepening depth-first search
- (转)NYU教授给写AI新闻的记者们写了一封推心置腹的信,你也应该读读
- AI的伦理问题
- 线程的调度问题
- 单幅图像的深度学习,对NYU数据集进行划分
- 进程间的调度问题
- 多核调度的问题研究
- spark的作业调度问题
- AI软件处理常出现的问题
- 目前AI研究所面临的问题
- 今天开始看关于调度的问题
- 一个经典的进程调度问题
- 回答朋友的问题(系统调度细节)
- 装配线调度问题 的 动态规划实现
- 双机流水作业调度问题的Johnson算法
- 多机调度问题的贪心解法
- 操作系统--进程调度的有关问题(1)
- JdbcDaoSupport.CLASS
- Android中AIDL
- 微信iOS 9适配总结
- 造成滑动试图卡顿原因之一:圆角
- Eclipe开发环境下的代码管理SVN
- nyu 的AI课的调度问题
- 【学习笔记】Android PopupWindow使用
- stm32 ds18b20 寄存器设置问题!
- ubuntu中netbean ide中文乱码
- iOS 给UIWebView添加头视图和尾视图
- 前台进程、可见进程、服务进程、后台进程、空进程
- memcpy函数
- Android LruCache图片缓存使用(二)
- C++实现进制转换(十进制转十六进制)