Question link http://cs.nyu.edu/courses/spring12/CSCI-GA.2560-001/prog1.html
Given the time, value, and order relationship of N tasks, find a feasible task subset so that the sum of time is not greater than deadline, and the sum of value is not less than targetvaule, the reverse sequence is not allowed.
Algorithm idea: the question has been given an algorithm, which is converted to a state space search (tree-structured state space search problem). First, the node topology is sorted to store the node relationship in the previous order, then, perform bfs on the status Search Tree, and press the feasible status into the queue. After the limit value is reached, perform iterative and in-depth search (iterative deepening depth-first search) based on the status in the queue ). The iterative Deep Search Algorithm starts from a node in the status space search tree, such as the root node. It iterates the DFS multiple times, and sets the maximum search depth for each DFS. The depth continues to increase to search for leaves. The pseudocode is as follows:
IDDFS(root, goal){ depth = 0 repeat { result = DLS(root, goal, depth) if (result is a solution) return result depth = depth + 1 }}
DLS(node, goal, depth) { if (depth == 0 and node == goal) return node else if (depth > 0) for each child in expand(node) DLS(child, goal, depth-1) else return no-solution}
For more information about iterative deep search algorithms, see Wikipedia http://en.wikipedia.org/wiki/Iterative_deepening_depth-first_search.
The source code for solving this problem is as follows:
// Http://cs.nyu.edu/courses/spring12/CSCI-GA.2560-001/#include <stdio. h >#include <vector >#include <map ># include <queue> using namespace STD; int tasknum; int targetvalue; int deadline; int queuemaxsize; typedef struct {bool * selected; int totalvalue; int totaltime; int currentdepth; // status of the current search} state; typedef struct {int time; int value;} node; // record the forward node of a certain point (that is, the task that must be completed before the task is executed) Map <int, vector <int> *> nodespre; int ** Edges; node * nodes; int * topologyresult; // an array of Topology Sorting results, which records the vertex numbers of each layer of the Status tree, int * nodetotopnode; queue <int> q; // used for topological sorting queue <State> stateq; // The State resstate of the queue used for state space search; // The status of the searched result bool hasresult; void initialstate (State & State) {state. selected = new bool [tasknum]; 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]; If (V = NULL) {return true;} vector <int >:: iterator it = V-> begin (); For (; it! = V-> end (); It ++) {// traverses all the forward nodes of the vertex, if no node is selected, false is returned. // enter the original number in the map array of nodetotopnode, it can be mapped to the new label after topological sorting. If (selected [nodetotopnode [* It] = false) return false;} return true;} bool BFS () {state root; // start point of the initial state space tree, that is, the root node initialstate (Root); stateq. push (Root); hasresult = false; while (! Stateq. empty () {If (stateq. size () = queuemaxsize) {// when this layer node can be selected, it will be pushed into two states and a status will pop up, therefore, the status queue will become larger and larger // after reaching the maximum queue limit, jump out of BFS and start the iteration to search for idsbreak first;} state = stateq. front (); stateq. pop (); State tempsubstate = copystate (State); If (tempsubstate. currentdepth = tasknum-1) {continue;} tempsubstate. currentdepth ++; int nodeid = topologyresult [tempsubstate. currentdepth]; // check whether all nodes before this point have been selected, and whether the accumulated value and time meet the requirements if (checkpreno De (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 ;}}// if the current layer node can be selected (no unselected In front of the node), a total of two statuses are pushed into the queue (select and not select ); // otherwise, it will be pushed into a state, that is, the State state of the layer node is not selected; tempsubstate2 = copystate (State); tempsubstate2.currentdepth ++; tempsubstate2.selected [tempsubstate2.currentdepth] = false; stateq. push (tempsubstate2);} return hasresult;} bool DFS (INT depth, state) {// The maximum depth is depth, and the state corresponding to the Start Node is stateState. currentdepth ++; int nodeid = topologyresult [State. currentdepth]; If (checkprenode (state. selected, nodeid) = true) {No De 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) {// here is the recursive 1if (DFS (depth-1, State) {return true ;}} corresponding to this layer node ;}}} // here, the recursion 0 corresponding to the layer node cannot be selected. The node must be taken out of State first. totalvalue-= node. value; State. totaltime-= node. time;} 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 is the maximum search depth 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 (findnoind Egreenode (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 ("Topology Sorting Result:"); For (INT m = 0; m <tasknum; m ++) {nodetotopnode [topologyresult [m] = m; // enter the original number, which can be mapped to the new number printf ("% d ", topologyresult [m]) ;}} void input () {scanf ("% 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", & 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 points to the vector container corresponding to lastnode if (V = NULL) {v = new vector <int>; nodespre [lastnode] = V ;} v-> push_back (prenode) ;}} void output () {printf ("returns ["); For (INT I = 0; I <tasknum; I ++) {If (resstate. selected [I] = 1) {// note that the fourth item in the result state is not assigned a value. It is also a non-zero number printf ("% d", topologyresult [I]);} printf ("] % d \ n", resstate. totalvalue, resstate. Totaltime) ;}int main () {input (); topologysort (); If (! BFS ()&&! IDS () {printf ("no solutions");} else output (); Return 0 ;}
Test code
# Include <iostream> # include <algorithm> # include <functional> # include <vector> # include <ctime> # include <cstdlib> # include <cmath> # define maxn 500 using namespace STD; int main () {int n,e = 1000, R [maxn], V [maxn], maxlen, P [maxn]; int I, j, D, M, minvd, maxvd, K = 0; int Dag [maxn] [maxn] = {0}; cout <"Please input the number of tasks in each example (less than 500) "<Endl; CIN> N; srand (unsigned (Time (null); fo R (I = 0; I <n; I ++) {R [I] = rand () % N + 1; V [I] = rand () % N + 1;} minvd = N * n * (1-2/SQRT (N)/4; maxvd = N * n * (1 + 2/SQRT (N)/4; D = rand () % (maxvd-minvd) + minvd + 1; M = rand () % (maxvd-minvd) + minvd + 1; maxlen = rand () % N + 1; // The maximum queue length // The dagvector is randomly generated below <int> myvector; vector <int>: iterator it; for (I = 0; I <n; ++ I) myvector. push_back (I); random_shuffle (myvector. begin (), myvector. en D (); cout <"myvector contains:"; for (IT = myvector. Begin (); it! = Myvector. end (); ++ it) {cout <"" <* It <","; P [k] = * it; k ++ ;} cout <Endl; cout <"R []:"; for (I = 0; I <n; I ++) {cout <R [I] <"," ;}cout <Endl; cout <"V []:"; for (I = 0; I <N; I ++) {cout <V [I] <"," ;}cout <Endl; cout <"D: "<D <Endl <" M: "<m <Endl; for (I = 0; I <n-1; I ++) // The traversal is actually an array for (j = I + 1; j <n; j ++) {Dag [p [I] [p [J] = rand () % 2; If (DAG [p [I] [p [J]) cout <p [I] <"" <p [J] <Endl ;}for (I = 0; I <n; I ++) {for (j = 0; j <n; j ++) {cout <Dag [I] [J] <";}cout <Endl ;} cout <Endl; cout <"the input for this example is as follows" <Endl; cout <n <"" <m <"" <D <"" <maxlen <Endl; for (I = 0; I <N; I ++) {cout <I <"" <V [I] <"" <R [I] <Endl ;}for (I = 0; I <n; I ++) {for (j = 0; j <n; j ++) {If (DAG [I] [J]) cout <I <"" <j <Endl ;}} cout <Endl; return 0 ;}