POJ 3249 Test for Job 解题报告 DP
2016-08-23 13:02
316 查看
题目意思:
给出一个有向图,但是这个图不一定联通而且保证无环。每个点上都有一个权值。问题是:从任意一个入度为0的点出发,目标是到达任意一个岀度为0的点,问所有的方法中,路上经过点的权值和最大为多少?
输入:
包含多组数据;
先输入两个数n,m;代表有n个点,m条边;
接下来n行,每行一个数,代表每个点的权值是多少;
接下来m行,每行两个数x,y,代表从x到y有一条路;
输出:路上经过的点权值和最大值
PS:有一点非常坑,点的权值可能是负数!(在这里感谢现在坐在我旁边的逗比 猪888 同学,是他提醒我有负数让我在WA了两次之后一遍AC);还有,记得是多组数据,记得数组清零;最后一点,数据范围,n是坑爹的100000,m是1000000;
现在大概讲一下思路是什么—->
先思考一下对于某一个中间点:
这个点要是需要走到某个岀度为0的点去,那么显然,他是需要走到他的一个儿子那里去的(貌似这是废话);
要是他的儿子已经计算出来最优解的话,那么就显然了;
这个点的走向显然是向最优解值最大的那个儿子~
那么,假设当前点为x,x最优解最大的那个儿子为y;
显然 dp[x]=max(dp[x],dp[y]+a[x]);
//a[x]是x点的权值
现在来考虑边界条件::::
其实不需要什么太多考虑
边界条件就是每个岀度为0的点啦
dp[x]=a[x]//x是某个出度为0的点
OK,现在放代码
给出一个有向图,但是这个图不一定联通而且保证无环。每个点上都有一个权值。问题是:从任意一个入度为0的点出发,目标是到达任意一个岀度为0的点,问所有的方法中,路上经过点的权值和最大为多少?
输入:
包含多组数据;
先输入两个数n,m;代表有n个点,m条边;
接下来n行,每行一个数,代表每个点的权值是多少;
接下来m行,每行两个数x,y,代表从x到y有一条路;
输出:路上经过的点权值和最大值
PS:有一点非常坑,点的权值可能是负数!(在这里感谢现在坐在我旁边的逗比 猪888 同学,是他提醒我有负数让我在WA了两次之后一遍AC);还有,记得是多组数据,记得数组清零;最后一点,数据范围,n是坑爹的100000,m是1000000;
现在大概讲一下思路是什么—->
先思考一下对于某一个中间点:
这个点要是需要走到某个岀度为0的点去,那么显然,他是需要走到他的一个儿子那里去的(貌似这是废话);
要是他的儿子已经计算出来最优解的话,那么就显然了;
这个点的走向显然是向最优解值最大的那个儿子~
那么,假设当前点为x,x最优解最大的那个儿子为y;
显然 dp[x]=max(dp[x],dp[y]+a[x]);
//a[x]是x点的权值
现在来考虑边界条件::::
其实不需要什么太多考虑
边界条件就是每个岀度为0的点啦
dp[x]=a[x]//x是某个出度为0的点
OK,现在放代码
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> using namespace std; const int maxn=100010,maxm=1000010; const int zhf=2147483647; int e,to[maxm],be[maxn],nxt[maxm],rd[maxn],cd[maxn],n,m;//这是链式前向星的一堆东西,还有入度(rd)岀度(cd)这些杂七杂八的 int dp[maxn];//这个数组是存放每个点的走到终点去最优解的 int a[maxn];//这个显然是每个点的权值 bool p[maxn];//用于记忆化搜索 void clear(){//每次记得清空 e=0; memset(to,0,sizeof(to)); memset(be,0,sizeof(be)); memset(nxt,0,sizeof(nxt)); memset(a,0,sizeof(a)); memset(rd,0,sizeof(rd)); memset(cd,0,sizeof(cd)); memset(dp,0,sizeof(dp)); memset(p,0,sizeof(p)); } void add(int x,int y){ //链式前向星的东西,没什么好讲的 to[++e]=y; nxt[e]=be[x]; be[x]=e; } int query(int x){//这个函数返回从点出发x的最优解是多少 if(p[x])return dp[x];//记忆化搜索 int ans=dp[x];//ans是迭代的东西 for(int i=be[x];i;i=nxt[i]){//调用链式前向星 int y=to[i];//显然,y是x的儿子之一 ans=max(ans,query(y)+a[x]);//状态转移方程 } p[x]=1;//表示已经计算过了 return dp[x]=ans; } int main(){ int i,j,k; while(scanf("%d%d",&n,&m)!=EOF){//显然 clear();//记得清零 for(i=1;i<=n;i++){ scanf("%d",a+i); dp[i]=-zhf;//记得有负数,这个坑死我了 } for(i=1;i<=m;i++){ int u,v; scanf("%d%d",&u,&v); add(u,v); cd[u]++; rd[v]++; //显然 } //for(j=1;j<=n;j++)for(i=be[j];i;i=nxt[i])printf("Start:%d -> To:%d\n",j,to[i]);return 0; //显然这个注释可以让你看看链式前向星在干什么 int ans=-zhf; for(i=1;i<=n;i++) if(cd[i]==0){ dp[i]=a[i]; p[i]=1; } for(i=1;i<=n;i++){ if(rd[i]==0) // printf("query(%d):%d\n",i,query(i)); //可以看看每一个点的答案啊~~~不过要注释掉那个if ans=max(query(i),ans); } cout<<ans<<endl; } return 0; }
相关文章推荐
- poj&nbsp;3249&nbsp;Test&nbsp;for&nbsp;Job&nbsp;dp(动态规…
- POJ 3249-Test for Job(拓扑排序&&DP)
- POJ 3249 Test for Job (dfs + dp)
- poj--3249 Test for Job(topsort + dp)
- POJ 3249 Test for Job 拓扑图DP
- poj 3249 Test for Job 图上dp(记忆化搜索)
- POJ 3249 Test for Job
- poj 3249 Test for Job (拓扑排序)
- POJ 3249 Test for Job(记忆化搜索)
- POJ_3249 Test for Job(拓扑)
- poj 3249 Test for Job (记忆化深搜)
- POJ 3249 Test for Job
- POJ 3249 Test for Job 拓扑排序+DP
- POJ3249 Test for Job(记忆化搜索)
- POJ-3249 Test for Job DAG最短路
- poj 3249 Test for Job
- POJ - 3249 Test for Job (DAG+topsort)
- POJ 3249 Test for Job(拓扑排序)
- POJ 3249 Test For Job
- POJ 3249 Test for Job(记忆化搜索)