codeforce 374C. Journey(dp)
2016-10-08 12:04
274 查看
传送门:C. Journey。
这是一个典型的图论里的题目,解法和Bellman-Ford算法很类似,题意要求从第一个点开始在规定时间内到达最多的点,而且最后一定要在n点(题目保证在规定时间内能到达n点),用dfs的话会超时,所以应该用dp。
设dp[i][j]表示经过i个点到达j点所用的最小时间,则题意变成在dp[i]
<=t里找最大的i就好了,外层循环遍历i的可能取值,内层循环遍历所有的边,状态转移方程为:
dp[i][v]=min(dp[i-1][u]+w(u,v)).
初始化的时候将所有点置为t+1就好了,这里t+1和inf的作用是一样的,本题中既然找小于等于t的,那么t+1和t+2和inf就没区别了。
还有就是要输出路径,所以要开辟一个数组father[i][j]来记录j点是经过i个点由father[i][j]到达的,然后最后根据最多能到达的点的个数回溯路径就好了。
#include <iostream>
#include <cstdio>
#include <cstring>
#define M 5005
using namespace std;
int n,m,t,pos;
struct node{
<span style="white-space:pre"> </span>int u,v,w;
}edge[M];
int dp[M][M],father[M][M];
int line[M];
void dpsolve()
{
<span style="white-space:pre"> </span>int u,v,w;
<span style="white-space:pre"> </span>for(int i=2;i<=n;i++)
<span style="white-space:pre"> </span>{
<span style="white-space:pre"> </span>for(int j=1;j<=m;j++)
<span style="white-space:pre"> </span>{
<span style="white-space:pre"> </span>u=edge[j].u;
<span style="white-space:pre"> </span>v=edge[j].v;
<span style="white-space:pre"> </span>w=edge[j].w;
<span style="white-space:pre"> </span>if(dp[i][v]>dp[i-1][u]+w)
<span style="white-space:pre"> </span>{
<span style="white-space:pre"> </span>dp[i][v]=dp[i-1][u]+w;
<span style="white-space:pre"> </span>father[i][v]=u;
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>if(dp[i]
<=t)
<span style="white-space:pre"> </span>pos=i;
<span style="white-space:pre"> </span>}
}
int main()
{
<span style="white-space:pre"> </span>scanf("%d%d%d",&n,&m,&t);
<span style="white-space:pre"> </span>for(int i=1;i<=m;i++)
<span style="white-space:pre"> </span>{
<span style="white-space:pre"> </span>scanf("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].w);
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>for(int i=0;i<=n;i++)
<span style="white-space:pre"> </span>for(int j=0;j<=n;j++)
<span style="white-space:pre"> </span>dp[i][j]=t+1;
<span style="white-space:pre"> </span>dp[1][1]=0;
<span style="white-space:pre"> </span>dpsolve();
<span style="white-space:pre"> </span>printf("%d\n",pos);
<span style="white-space:pre"> </span>int index=0,tt=n;
<span style="white-space:pre"> </span>for(int j=pos;j>0;j--)
<span style="white-space:pre"> </span>{
<span style="white-space:pre"> </span>line[index++]=tt;
<span style="white-space:pre"> </span>tt=father[j][tt];
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>printf("%d",line[index-1]);
<span style="white-space:pre"> </span>for(int j=index-2;j>=0;j--)
<span style="white-space:pre"> </span>printf(" %d",line[j]);
return 0;
}
这是一个典型的图论里的题目,解法和Bellman-Ford算法很类似,题意要求从第一个点开始在规定时间内到达最多的点,而且最后一定要在n点(题目保证在规定时间内能到达n点),用dfs的话会超时,所以应该用dp。
设dp[i][j]表示经过i个点到达j点所用的最小时间,则题意变成在dp[i]
<=t里找最大的i就好了,外层循环遍历i的可能取值,内层循环遍历所有的边,状态转移方程为:
dp[i][v]=min(dp[i-1][u]+w(u,v)).
初始化的时候将所有点置为t+1就好了,这里t+1和inf的作用是一样的,本题中既然找小于等于t的,那么t+1和t+2和inf就没区别了。
还有就是要输出路径,所以要开辟一个数组father[i][j]来记录j点是经过i个点由father[i][j]到达的,然后最后根据最多能到达的点的个数回溯路径就好了。
#include <iostream>
#include <cstdio>
#include <cstring>
#define M 5005
using namespace std;
int n,m,t,pos;
struct node{
<span style="white-space:pre"> </span>int u,v,w;
}edge[M];
int dp[M][M],father[M][M];
int line[M];
void dpsolve()
{
<span style="white-space:pre"> </span>int u,v,w;
<span style="white-space:pre"> </span>for(int i=2;i<=n;i++)
<span style="white-space:pre"> </span>{
<span style="white-space:pre"> </span>for(int j=1;j<=m;j++)
<span style="white-space:pre"> </span>{
<span style="white-space:pre"> </span>u=edge[j].u;
<span style="white-space:pre"> </span>v=edge[j].v;
<span style="white-space:pre"> </span>w=edge[j].w;
<span style="white-space:pre"> </span>if(dp[i][v]>dp[i-1][u]+w)
<span style="white-space:pre"> </span>{
<span style="white-space:pre"> </span>dp[i][v]=dp[i-1][u]+w;
<span style="white-space:pre"> </span>father[i][v]=u;
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>if(dp[i]
<=t)
<span style="white-space:pre"> </span>pos=i;
<span style="white-space:pre"> </span>}
}
int main()
{
<span style="white-space:pre"> </span>scanf("%d%d%d",&n,&m,&t);
<span style="white-space:pre"> </span>for(int i=1;i<=m;i++)
<span style="white-space:pre"> </span>{
<span style="white-space:pre"> </span>scanf("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].w);
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>for(int i=0;i<=n;i++)
<span style="white-space:pre"> </span>for(int j=0;j<=n;j++)
<span style="white-space:pre"> </span>dp[i][j]=t+1;
<span style="white-space:pre"> </span>dp[1][1]=0;
<span style="white-space:pre"> </span>dpsolve();
<span style="white-space:pre"> </span>printf("%d\n",pos);
<span style="white-space:pre"> </span>int index=0,tt=n;
<span style="white-space:pre"> </span>for(int j=pos;j>0;j--)
<span style="white-space:pre"> </span>{
<span style="white-space:pre"> </span>line[index++]=tt;
<span style="white-space:pre"> </span>tt=father[j][tt];
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>printf("%d",line[index-1]);
<span style="white-space:pre"> </span>for(int j=index-2;j>=0;j--)
<span style="white-space:pre"> </span>printf(" %d",line[j]);
return 0;
}
相关文章推荐
- Towers codeforce +dp
- codeforce 382 div2 E —— 树状dp
- Codeforce 题目118D. Caesar's Legions(DP背包)
- codeforce-404D---Minesweeper 1D(dp)
- CodeForce 505C Mr. Kitayuta(DP+DFS)
- codeforce 580D Kefa and Dishes (状压DP)
- codeforce 148D. Bag of mice[概率dp]
- codeforce 855C. Helga Hufflepuff's Cup 树形DP
- codeforce 741 B. Arpa's weak amphitheater and Mehrdad's valuable Hoses(背包 dp)
- codeforce Ilya and Roads (区间dp)
- Codeforce 486D(树形dp)
- codeforce 455A—— DP—— Boredom
- Codeforce 792C(dp)
- Code Force 229 D (DP)
- codeforce 149D Coloring Brackets (区间DP)
- Codeforce 65D - Harry Potter and the Sorting Hat(DP+hash+set)
- codeforce 743 D. Chloe and pleasant prizes (树形dp)
- Codeforce 540D(概率dp)
- Codeforce 65D - Harry Potter and the Sorting Hat(DP+hash+set)
- Codeforce 149D(区间dp+括号匹配)