自从省赛受打击后好久没写题目了,今天写了这个就犯了一个特别愚蠢的错误,查了一天啊。。。
http://www.lydsy.com/JudgeOnline/problem.php?id=1003
题意:略
思路:动态规划转移方程为:
dp[i] = min(dp[i], dis[k][i] * (i - k + 1) + K)
其中 dp[i] 表示从第一天到第 i 天的最小花费, dis[k][i] 表示地 k 天到第 i 天都走同一条路的最小花费,其中 dis[k][i] 可以用spfa暴力求解
#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
int n, m, K, e;
const int inf = 0x3f3f3f3f;
struct Side{
int to, val, next;
};
int dp[105];
int head[25];
Side side[10005];
bool node[25][105];
queue<int> que;
void add(int x, int y, int val, int pos){
side[pos].to = y;
side[pos].val = val;
side[pos].next = head[x];
head[x] = pos;
}
inline bool Judge(int w, int s, int t){
for(int i = s; i <= t; i++){
if(!node[w][i])
return false;
}
return true;
}
int Spfa(int datas, int datat, int s, int t){
int dis[25];
bool vis[25];
memset(dis, 0x3f, sizeof(dis));
memset(vis, false, sizeof(vis));
dis[s] = 0;
vis[s] = true;
que.push(s);
while(!que.empty()){
int r = que.front();
que.pop();
vis[r] = false;
for(int i = head[r]; ~i; i = side[i].next){
int w = side[i].to;
if(dis[w] > dis[r] + side[i].val && Judge(w, datas, datat)){
dis[w] = dis[r] + side[i].val;
if(!vis[w]){
que.push(w);
vis[w] = true;
}
}
}
}
return dis[t];
}
int main()
{
while(~scanf("%d%d%d%d", &n, &m, &K, &e)){
int x, y, val;
memset(dp, 0x3f, sizeof(dp));
memset(head, -1, sizeof(head));
memset(node, true, sizeof(node));
for(int i = 0; i < e; i++){
scanf("%d%d%d", &x, &y, &val);
add(x, y, val, i << 1);
add(y, x, val, i << 1 | 1);
}
int temp = 0;
int pos, l, r;
scanf("%d", &temp);
while(temp--){
scanf("%d%d%d", &pos, &l, &r);
for(int i = l; i <= r; i++){
node[pos][i] = false;
}
}
dp[0] = 0;
for(int i = 1; i <= n; i++){
for(int k = 0; k < i; k++){
int res = Spfa(k+1, i, 1, m);
dp[i] = min(dp[i], dp[k] + res * (res == inf ? 1 : (i - k)) + K);
}
}
printf("%d\n", dp[n] - K);
}
return 0;
}