您的位置:首页 > 其它

POJ-1949(模拟或DP)

2014-06-08 21:19 381 查看
一、很容易想到如下的模拟过程:

(0)使没有先决条件的工作进入服务窗口

(1)找到所有正在处理的工作中剩余所需时间最少的工作所需的时间T

(2)将所有窗口剩余所需时间减去T,如果该窗口的工作已经完成,则将其当做先决条件的工作所需的先决条件的数量减一,如果这一工作已经没有任何先决条件,则将其送入一个窗口开始进行服务

(3)如果所有窗口都已经没有在进行服务,则过程停止

根据以上步骤,很容易写出模拟代码:



#include <cstdio>
#include <vector>
#include <list>
using namespace std;
#define MAX 10001

struct Job{
int timeNeeded;
int numberOfPrerequisites;
vector<int> nextJobs;
} arr[MAX];
int N;

int getLeastTimeNeeded(const list<int>& jobList)
{
list<int>::const_iterator iter = jobList.begin(), eter = jobList.end();
int t = arr[*iter++].timeNeeded, i;
for(; iter != eter; ++iter){
i = *iter;
if(t > arr[i].timeNeeded) t = arr[i].timeNeeded;
}
return t;
}
void insertSubsequentJobs(list<int>& jobList, int doneID)
{
if(arr[doneID].nextJobs.empty()) return;
for(int i = 0, n = arr[doneID].nextJobs.size(); i < n; ++i){
int j = arr[doneID].nextJobs[i];
if(--arr[j].numberOfPrerequisites == 0) jobList.push_front(j);
}
}

int main()
{
//step 1: input job count
scanf("%d", &N);
//step 2: input job graph
int i, j, k;
for(i = 1; i <= N; ++i){
scanf("%d %d", &arr[i].timeNeeded, &arr[i].numberOfPrerequisites);
for(j = 0; j < arr[i].numberOfPrerequisites; ++j){
scanf("%d", &k);
arr[k].nextJobs.push_back(i);
}
}
//step 3: initialize job line
list<int> jobList;
list<int>::iterator iter, eter;
for(i = 1; i <= N; ++i){
if(arr[i].numberOfPrerequisites == 0) jobList.push_front(i);
}
//step 4: schedule jobs
int totalTime = 0, time;
while(!jobList.empty()){
//find out the job which need least time now
totalTime += time = getLeastTimeNeeded(jobList);
//minus each job with time
for(iter = jobList.begin(), eter = jobList.end(); iter != eter; ){
i = *iter;
arr[i].timeNeeded -= time;
if(arr[i].timeNeeded == 0){
iter = jobList.erase(iter);
insertSubsequentJobs(jobList, i);
}
else ++iter;
}
}
//step 5: print result
printf("%d", totalTime);

return 0;
}
二、实际上此题还可以看做树型DP的问题,把每一个工作看成一个节点,将先决条件看成其子节点,则dp[parent] = max{dp[children] + costOfParent},并且题中"Farmer John's list of chores is nicely ordered, and chore K (K > 1) can
have only chores 1,.K-1 as prerequisites."说明我们可以边读入边DP而不用保存节点信息:



#include <cstdio>
#define MAX 10001

int N, dp[MAX] = {0};

int main()
{
scanf("%d", &N);
int i, j, k, n, t, ans = 0;
for(i = 1; i <= N; ++i){
scanf("%d %d", &t, &n);
if(n == 0) dp[i] = t;
else{
for(j = 0; j < n; ++j){
scanf("%d", &k);
if(dp[k] + t > dp[i]) dp[i] = dp[k] + t;
}
}
if(dp[i] > ans) ans = dp[i];
}
printf("%d", ans);

return 0;
}

从时间上来看,用了DP之后,速度并没有得到质的改变,目测是因为数据量太大,大部分时间消耗在了scanf上:

当大部分时间用在IO上时,改进算法的作用微乎其微
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: