NOIP 2017 Day1 题3:逛公园 最短路径+动态规划

摘自:http://blog.csdn.net/enjoy_pascal/article/details/78592786   写的很简短

analysis

有人说这是防AK题?不算吧……(只不过我并没有做出来顶乱用)

首先用邻接表存边跑一遍spfa,dis[i]表示1到i的最短路长度(不要和我说你不会spfa) 
f[i][j]表示从1到i的所有路径里,比dis[n]大K的路径条数 
所以有

f[i][j]=f[k][dis[i]dis[k]+jlen[i][k]]

看到这个,你以为是 DP ? 
记忆化搜索!  
我们从 n 开始 倒着搜索 ,若 dis[i]dis[k]+jlen[i][k]0 当然也就不搜索了

那么我们最大的敌人——判0环呢? 
f[x][y]这个状态在一遍dfs里出现两次,那就是有0环,return就好,开个数组标记一下

finally

ans=(i=0nf[n][i])modp

他的代码。我在写。。。。。。已经通过了7组数据 ,0环还在研究

/*输入
1
5 10 0 595078320
1 2 1
2 5 1
2 1 2
5 2 1
2 3 1
3 5 1
1 5 2
4 1 1
3 1 2
4 2 1
输出 2
我的输出:4 未通过*/

#include 
using namespace std;
const  int MAX_N=100001;
struct edge{
    int to;
    int cost;
};
vector  G[MAX_N];
vector  ReG[MAX_N];

int dis[MAX_N];
int N,M,K,pmod;
int dp[MAX_N][51];
bool roll;

void input(){

    for(int i=0;i> N >> M >> K >> pmod;

    for(int i=1;i<=M;i++){

        int a,b,c; cin >> a >> b>>c;
        G[a].push_back(    (edge){b,c} );
        ReG[b].push_back(  (edge){a,c} );

    }

    memset(dp, 0 ,sizeof(dp));
    dp[1][0]=1;
    fill(dis ,dis+N+1, 200000000);
    roll=false;

}


int  dfs(int v,int k){
    if(dp[v][k]!=0) return dp[v][k];
    //used[v]=true;
    for(  int j=0; j P;
    priority_queue,greater

> que; dis[1] = 0; que.push( P(0,1)); while( !que.empty()){ P p = que.top(); que.pop(); int v= p.second; if( dis[v] < p.first ) continue; for( int i=0 ; i dis[v] + e.cost ){ dis[e.to] = dis[v] + e.cost; que.push( P( dis[e.to] , e.to )); } } } } int main() { //freopen("park.in","r",stdin); //freopen("park.out","w",stdout); int T;cin>>T; while(T--){ input(); dijkstra(); int ans=0; for(int i=0;i<=K; i++){ ans = ( ans + dfs(N,i) ) % pmod; } //if(roll) cout << -1 <







NOIP 2017 逛公园  动态规划!


http://blog.csdn.net/qq_38678604/article/details/78572603#t4  这一篇写得好


https://www.cnblogs.com/CQzhangyu/p/7825839.html



https://www.cnblogs.com/Dndlns/p/7895996.html 



//#define debug
#include 
using namespace std;
const  int MAX_N=1000001;
struct edge{
    int to;
    int cost;
};
vector  G[MAX_N];
//  vector  ReG[MAX_N];
long long  dis[MAX_N];   //存储最短路径






int N,M,K,pmod;


// bool used[MAX_N];


//int rudu[MAX_N] ; // 存储 入度的值
int dp[MAX_N][51];




vector O[MAX_N];  //为零边建立图
vector RO[MAX_N];  //零边建立方向图






void input(){


    cin >> N >> M >> K >> pmod;


    for(int i=1;i<=M;i++){


        int a,b,c; cin >> a >> b>>c;
        G[a].push_back(  (edge){b,c} );
       // rudu[b]++;


        //ReG[b].push_back( (edge){a,c});
        if( c==0) {
                O[a].push_back(  (edge){b,c} ) ;
                RO[b].push_back(  (edge){a,c} ) ;
        }


    }


    memset(dp, 0 ,sizeof(dp));


    dp[1][0]=1;


    fill(dis ,dis+N+1, 2000);


//     for(int i=1;i<=M;i++){
//
//             for( int j=0;j vs  ; //后序遍历的顶点表
bool atO[MAX_N];




void dfs(int v){
    used[v]=true;
    for(  int j=0; j=0 ;i--){
   //for(int i=0; i P;
    priority_queue,greater

>  que;     dis[1] = 0;     que.push( P(0,1));     while( !que.empty()){         P p = que.top(); que.pop();         int v= p.second;         if( dis[v] < p.first ) continue;         for( int i=0 ; i dis[v] + e.cost ){                 dis[e.to] =  dis[v] + e.cost;                 que.push(  P( dis[e.to] , e.to ));             }         }     }  #ifdef debug       cout< qq;         qq.push(1);         us[1]=true;         while(!qq.empty()){             int s=qq.front();   qq.pop();             if( roll::atO[s] ) {    return -1;         }             for(  int j=0; j < G[s].size(); j++){                 edge e =  G[s][j];                 if(   e.cost + dis[s] - dis[e.to] > K ||  e.cost + dis[s] - dis[e.to]<0 ) continue;//泪!!                 else                 if( !us[e.to]) { qq.push(e.to) ; us[e.to] =true; };                 for(int k=0; k<=K; k++){                     int kk = k +  e.cost + dis[s] - dis[e.to] ;                     if(  (kk>=0) && (kk <= K) ){                             dp[e.to][ kk ]  = (  dp[e.to][ kk ]  +  dp[s ][ k ] );                             #ifdef debug                               cout << "from " <<  s << "dp[" << e.to << "]"                                    << "[" <<  kk     << "] :"                                    <<    dp[e.to][ kk] << endl;                             #endif // debug                     }                 }             }         }         return 1;    } int main() {     //freopen("park.in","r",stdin);     //freopen("park.out","w",stdout);     int t;cin>>t;     while(t--){         input();         dijkstra();         roll::scc();         if( BFS()==-1 ) cout << -1;         else{             int ans = 0;             for(int i=0;i<=K; i++){                        // cout <<"dp[N][i]" << dp[N][i];                 ans = ( ans + dp[N][i ] ) % pmod;             }             cout <<  ans<


你可能感兴趣的:(信息学奥赛(NOIP),动态规划,NOIP真题)