大大体题意:
给你一个有向图,要求从1点出发,到n 点结束,要求在T时间内 经过尽可能多的城市,输出最大数量,和路径!
思路:
dp思想:比赛时自己想的太简单了,果然wa了!
令dp[i][j]表示用i个点 到目的地 j 的最小时间!
那么 直接枚举每个i 点了!
枚举目的地不好转移,那么 就枚举每个边,反正每个边也经过所有的点,也可以完成目的!
那么如果u 能到v!
那么dp[i][v] = min(dp[i-1][u] + w) 时间比dp[i][v]小就可以转移,然后更新上一个节点记录路径!
最后只需要找到 最后一个 dp[i][n] <=T的即可! 这样保证了路径最长 且 时间符合要求!!!
DP递推形式代码:
#include
using namespace std;
const int maxn = 5000 + 10;
int dp[maxn][maxn],la[maxn][maxn];
const int inf = 0x3f3f3f3f;
stacksk;
struct Node{
int u,v,w;
void read(){
scanf("%d %d %d",&u, &v, &w);
}
}p[maxn];
int main(){
int n,m, k;
scanf("%d %d %d",&n, &m, &k);
for (int i = 0; i < m; ++i){
p[i].read();
}
memset(dp,inf,sizeof dp);
memset(la,-1,sizeof la);
dp[1][1] = 0;
int pos;
for (int i = 2; i <= n; ++i){
for (int j = 0; j < m; ++j){
int u = p[j].u;
int v = p[j].v;
int w = p[j].w;
if (dp[i-1][u] + w < dp[i][v]){
dp[i][v] = dp[i-1][u] + w;
la[i][v] = u;
//printf("%d %d\n",u,v);
//printf("^^^^ %d\n",dp[3][4]);
}
}
if (dp[i][n] <= k){
pos = i;
}
}
printf("%d\n",pos);
int cur = n;
while(cur != -1){
sk.push(cur);
cur = la[pos--][cur];
}
// printf("&& %d\n",la[pos][2]);
int cnt = 0;
while(!sk.empty()){
if (cnt++)printf(" ");
printf("%d",sk.top());
sk.pop();
}
puts("");
return 0;
}
DP记忆化搜索代码:(需要仔细处理好边界不合法的情况,RE了几回!)
# include
using namespace std;
const int maxn = 5000 + 10;
vector >g[maxn];
stacksk;
struct Node{
int u,v,w;
void read(){
scanf("%d %d %d",&u,&v,&w);
}
}p[maxn];
int dp[maxn][maxn];
int la[maxn][maxn];
int dfs(int k,int m){
int& ans = dp[k][m];
if (ans != -1)return ans;
if (k == 1 && m == 1) return ans = 0;
if (k < 1 || m < 1)return 0x3f3f3f3f;
ans = 0x3f3f3f3f;
for (int i = 0; i < g[m].size(); ++i){
int v = g[m][i].first;
int w = g[m][i].second;
int t = dfs(k-1,v) + w;
if (ans > t){
ans = t;
la[k][m] = v;
}
}
return ans;
}
int main(){
int n,m,T;
scanf("%d %d %d", &n, &m, &T);
for (int i = 0; i < m; ++i){
p[i].read();
g[p[i].v].push_back(make_pair(p[i].u,p[i].w));
}
memset(dp,-1,sizeof dp);
memset(la,-1,sizeof la);
int pos;
for (int i = n; i >= 2; --i){
if (dfs(i,n) <= T){
pos = i;
break;
}
}
printf("%d\n",pos);
int cur = n;
while(cur != -1){
sk.push(cur);
cur = la[pos--][cur];
}
int cnt =0;
while(!sk.empty()){
if (cnt++)printf(" ");
printf("%d",sk.top());
sk.pop();
}
puts("");
return 0;
}