您的位置:首页 > 其它

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,现在放代码

#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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: