• bzoj1003 trans DP


    最初的印象是网络流之类的东西,但好像不是。

    想了一下,没什么思路,就网上看了一下,有人说是DP,然后就自己想DP的做法,最开始想的状态是:dp[n][s] 第n天走s这条路,前n天最小的代价,但发现路径不好表示,并且m=20时s最大就是10^6级别了,所以放弃了这个状态。

    打开题解,发现题解的状态不需要记录s,即dp[n]表示前n天最小的代价和,然后用一个辅助数组mdis[i][j]表示从第i天到第j天所有限制共同作用下的图的最短路。转移:

      dp[i] = min( mdis[1][i]*i, dp[j]+mdis[j+1][i]*(i-j)+K | j in [1,i) }

    的确很好,也很自然(对于一个最优解,必定是由一些“路径改变点”组成,而两个“路径改变点"之间走的一定是满足该区间限制下的最短路,我们每次只需要枚举最后一个路径改变点,就可以转移了)。有点像一个多决策问题(对于每一天,决策是改变或不改变路径)。

      1 /**************************************************************
      2     Problem: 1003
      3     User: idy002
      4     Language: C++
      5     Result: Accepted
      6     Time:28 ms
      7     Memory:860 kb
      8 ****************************************************************/
      9  
     10 #include <cstdio>
     11 #include <cstring>
     12 #include <queue>
     13 #include <vector>
     14 #define maxn 110
     15 #define maxm 25
     16 #define inf 0x3f3f3f3f
     17 using namespace std;
     18  
     19 int n, m, e, K;
     20  
     21 vector<int> g[maxm], wght[maxm];
     22 bool gave[maxm][maxn];
     23 bool cave[maxm];
     24  
     25 int mdis[maxn][maxn];
     26 int dis[maxm];
     27 bool done[maxm];
     28 int dp[maxn];
     29  
     30  
     31 void input() {
     32     scanf( "%d%d%d%d", &n, &m, &K, &e );
     33     for( int i=1,u,v,w; i<=e; i++ ) {
     34         scanf( "%d%d%d", &u, &v, &w );
     35         g[u].push_back(v);
     36         g[v].push_back(u);
     37         wght[u].push_back(w);
     38         wght[v].push_back(w);
     39     }
     40     memset( gave, 1, sizeof(gave) );
     41     int d;
     42     scanf( "%d", &d );
     43     for( int i=1,u,a,b; i<=d; i++ ) {
     44         scanf( "%d%d%d", &u, &a, &b );
     45         for( int i=a; i<=b; i++ )
     46             gave[u][i] = false;
     47     }
     48 }
     49  
     50 struct Stat {
     51     int u, dis;
     52     Stat( int u, int dis ):u(u),dis(dis){}
     53     bool operator<( const Stat & b ) const {
     54         return dis>b.dis;
     55     }
     56 };
     57 int dijstra( int s, int d ) {
     58     priority_queue<Stat> hp;
     59     memset( done, false, sizeof(done) );
     60     memset( dis, 0x3f, sizeof(dis) );
     61     dis[s] = 0;
     62     hp.push( Stat(s,0) );
     63     while( !hp.empty() ) {
     64         int u = hp.top().u;
     65         hp.pop();
     66         if( done[u] ) continue;
     67         done[u] = true;
     68         if( u==d ) return dis[d];
     69         for( int t=0; t<g[u].size(); t++ ) {
     70             int v = g[u][t];
     71             int w = wght[u][t];
     72             if( !cave[v] ) continue;
     73             if( dis[v]>dis[u]+w ) {
     74                 dis[v]=dis[u]+w;
     75                 hp.push( Stat(v,dis[v]) );
     76             }
     77         }
     78     }
     79     return inf;
     80 }
     81 void prep() {
     82     memset( mdis, 0x3f, sizeof(mdis) );
     83     for( int i=1; i<=n; i++ ) {
     84         memset( cave, 1, sizeof(cave) );
     85         for( int j=i; j<=n; j++ ) {
     86             for( int u=1; u<=m; u++ )
     87                 cave[u] &= gave[u][j];
     88             mdis[i][j] = dijstra(1,m);
     89         }
     90     }
     91 }
     92 void work() {
     93     for( int i=1; i<=n; i++ ) {
     94         if( mdis[1][i]!=inf ) 
     95             dp[i] = mdis[1][i]*i;
     96         else dp[i]=inf;
     97         for( int j=1; j<i; j++ )
     98             if( mdis[j+1][i]!=inf ) 
     99                 dp[i] = min( dp[i], dp[j]+mdis[j+1][i]*(i-j)+K );
    100     }
    101     printf( "%d
    ", dp[n] );
    102 }
    103 int main() {
    104     input();
    105     prep();
    106     work();
    107 }
    View Code
  • 相关阅读:
    zabbix 监控获取源码包的地址
    为MongoDB加集群验证的关键点
    Mongodb 集群加keyFile认证
    Prometheus完整的部署方案+实战实例
    如何让你的linux的命令行变得很炫
    redis实现加锁的几种方法示例详解
    phpquerylist 抓取数据详解
    mysql 主从配置,主-》windows,从-》centos6.5
    VMware 虚拟机centos下链接网络配置
    【Mysql】表链接
  • 原文地址:https://www.cnblogs.com/idy002/p/4294069.html
Copyright © 2020-2023  润新知