• BZOJ 1003


    从这篇开始换字体。。

    数据范围很小。。直接暴力DP之即可。。

    感觉跟之前做的1597的DP很像,都是基于连续区间的DP,应该也可以用斜率优化。。

    还感觉跟某次CodeVS模拟赛的题的一道变态题(多面体原谅我。。)很像。。只不过那道题最后是二分图匹配。。

    题解详见代码注释。。我只想吐槽。。窝一遇到什么n m d k p都出来的题,就很容易打错变量名(又因为这WA了三四次!。。这回我一开始就写成了输出f[n](这些变量与题目意义不同...自己改了一下。。)以后,要么把变量名搞长一点、搞有意义一点;要么就再码和调的过程中小心小心再小心(简直非人哉。。

    // BZOJ 1003 
    // 跟某道奇怪的变态的codevs月赛题(喂东西吃)很像。。
    
    #include <cstdio>
    #include <cstring>
    #include <vector>
    #include <queue>
    #include <algorithm>
    using namespace std;
    
     const int D=100+5, N=20+5, M=N*N*2+5, P=20*100*100+5;
    
     #define rep(i,a,b) for (int i=a; i<=b; i++)
     #define dep(i,a,b) for (int i=a; i>=b; i--)
     #define read(x) scanf("%d", &x)
     #define fill(a,x) memset(a, x, sizeof(a))
     #define LL long long
    
     int n, m, d, k, p, u, v, w, l, r;
     LL f[D], cost[D][D];
    
     struct Graph {
        int s, from[M], to[M], pre[M], dis[M], last[N];
        void init() { s=-1; fill(last, -1); }
        void ine(int a, int b, int w) {
            s++;
            from[s]=a, to[s]=b, pre[s]=last[a], dis[s]=w;
            last[a]=s;
        }
        void ine2(int a, int b, int w) {
            ine(a, b, w);
            ine(b, a, w);
        }
     } G;
     #define reg(i,G,u) for (int i=G.last[u]; i!=-1; i=G.pre[i])
    
     struct List_Pair {
     	int s, pre[P], a[P], b[P], las[N];
     	void init() { s=-1; fill(las, -1); }
     	void push_back(int x, int a_, int b_) {
     		s++;
     		pre[s]=las[x]; a[s]=a_; b[s]=b_;
     		las[x]=s; 
     	}
     } mes;
     #define rel(i,L,x) for (int i=L.las[x]; i!=-1; i=L.pre[i])
    
     struct Node {
     	int id, dis;
     	bool operator < (const Node x) const { return dis>x.dis; }
     	Node(int id_, int dis_) { id=id_; dis=dis_; }
     };
     
     bool done[N], ok[N]; // ok[i]表示当前时间区间i点是否可走
     int Dijkstra(int l, int r) {
     	priority_queue<Node> Q;
     	int d[N]; 
     	fill(d, 0x3f); fill(done, false); fill(ok, true); 
     	// 预处理ok[],只要当前时间区间有一天不可走,那么ok[i]就置为false
     	rep(i,2,n-1) rel(j,mes,i) 
     	    if (max(l, mes.a[j])<=min(r, mes.b[j])) { ok[i]=false; break; } 
     	Q.push(Node(1,0)); d[1]=0;
     	while (!Q.empty()) {
     		Node Nx=Q.top(); Q.pop();
     		int x=Nx.id;
     		if (done[x]) continue;
     		done[x]=true;
     		reg(i,G,x) {
     			int y=G.to[i], w=G.dis[i];
     			if (!done[y] && d[y]>d[x]+w && ok[y]) {
     				d[y]=d[x]+w;
     				Q.push(Node(y, d[y]));
     			}
     		}
     	}
     	return d[n];
     }
    
    int main()
    {
    	G.init(); mes.init();
    	scanf("%d%d%d%d", &d, &n, &k, &m);
    	rep(i,1,m) scanf("%d%d%d", &u, &v, &w), G.ine2(u, v, w); 
    	read(p);
    	rep(i,1,p) scanf("%d%d%d", &u, &l, &r), mes.push_back(u, l, r);
    
        // 预处理出cost[i][j]表示第i天到第j天不改变航线所需要的最小花费
        // 即:当i~j天可走节点的并集可以保证能到达目的地时,则最短路跑一遍即可;否则为无穷大
        rep(i,1,d)
     	  rep(j,i,d) 
     	    cost[i][j]=Dijkstra(i, j);
    
        // 对花费进行DP:设f[i]表示前i天的最少花费
     	// 我们枚举最后一次改变路线的时间j,则有f[i] = min { f[j] + cost[j][i] } + k
     	// 注意,还可以不更改路线,此时的花费为cost[1][i]
        rep(i,1,d) {
        	f[i]=(LL)cost[1][i]*i;
            rep(j,1,i-1) f[i]=min(f[i], f[j]+cost[j+1][i]*(i-j)+k);
        }
    
        printf("%lld
    ", f[d]);
    	
    	return 0;
    }
    


  • 相关阅读:
    NET CORE 数据库迁移
    VUE3.0 解析svg文件
    关于ElementUI的样式不生效
    git命令
    vue 2.x的跨域问题
    Putty 重新启动 linux sqlserver服务
    aspnetcore之session
    Syncfusion 在 core 的架构
    TortoiseSVN创建/合并分支
    正则表达式知识点整理
  • 原文地址:https://www.cnblogs.com/yearwhk/p/5119862.html
Copyright © 2020-2023  润新知