51nod_1445 变色DNA 最短路模板 奇妙思维

这是一道最短路模板题,但是在理解题意和提出模型的阶段比较考验思维,很容易想到并且深深进入暴力拆解题目的无底洞当中。

题意是说:给出一个邻接矩阵,在每个点时,走且仅走向,合法路径中编号最小的点。问题是是否能够从0点走向n-1点。如果可以走到,求出,最少应当删除几个合法边(如果(1,2)(2,1)(2,3)同时合法,前两个边就会不停的循环,这时候必须删掉(2,1)才能够让(2,3)这条边被走到,从而到达新的节点)。

题解:重新定义变得权重:按照题意变得权重应当每次是1,但是显然在这道题的设定下,这个权重并没有意义。因此应当重新定义每条边的权重:使得邻接矩阵path[i][j]代表的含义是:如果要合法的走过这条边,应当删除前面的几条边?

 

普通的dijkstra:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 
 4 long long cases,n,m;
 5 const long long MAXN=50+23;
 6 const long long INF=1e12+233;
 7 long long path[MAXN][MAXN];
 8 long long dp[MAXN];
 9 
10 void init()
11 {
12     cin>>n;    
13     for(int i=0;i<n;++i)
14     {
15         dp[i]=INF;long long point=0;
16         for(int j=0;j<n;++j)
17             {
18                 path[i][j]=INF;
19                 char c;
20                 cin>>c;
21                 
22                 if(c!='N')
23                 {
24                     path[i][j]=point;
25                     point++;
26                 }
27             }
28     }
29 }
30 bool v[MAXN];
31 void dijkstra()
32 {
33     memset(v,0,sizeof(v));
34     dp[0]=0;int x=0;
35     for(int i=0;i<n;++i)
36     {
37         long long mini=INF;
38         for(int j=0;j<n;++j)
39         {
40             if(!v[j]&&dp[j]<mini)
41             {
42                 mini=dp[j];
43                 x=j;
44             }
45         }v[x]=1;
46         for(int j=0;j<n;++j)
47         {
48             dp[j]=min(dp[j],dp[x]+path[x][j]);
49         }
50     }
51     
52     if(dp[n-1]==INF)cout<<"-1"<<endl;
53     else cout<<dp[n-1]<<endl;
54 }
55 
56 int main()
57 {
58     cin.sync_with_stdio(false);
59     cin>>cases;
60     for(int itee=0;itee<cases;++itee)
61     {
62         init();
63         dijkstra();
64     }
65     return 0;
66 }

 两行代码的解决方案:

1 #include<bits/stdc++.h>
2 using namespace std;long long cases,n,m;const long long MAXN=50+23;const long long INF=1e12+233;long long path[MAXN][MAXN];long long dp[MAXN];void init(){    cin>>n;        for(int i=0;i<n;++i)    {        dp[i]=INF;long long point=0;        for(int j=0;j<n;++j)            {                path[i][j]=INF;                char c;                cin>>c;                                if(c!='N')                {                    path[i][j]=point;                    point++;                }            }    }}bool v[MAXN];void dijkstra(){    memset(v,0,sizeof(v));    dp[0]=0;int x=0;    for(int i=0;i<n;++i)    {        long long mini=INF;    for(int j=0;j<n;++j)    {        if(!v[j]&&dp[j]<mini)    {    mini=dp[j];    x=j;    }    }v[x]=1;    for(int j=0;j<n;++j)    {            dp[j]=min(dp[j],dp[x]+path[x][j]);}}    if(dp[n-1]==INF)cout<<"-1"<<endl;    else cout<<dp[n-1]<<endl;}int main(){    cin.sync_with_stdio(false);    cin>>cases;    for(int itee=0;itee<cases;++itee)    {        init();        dijkstra();    }    return 0;}

 

posted @ 2017-08-09 16:26  六花的邪王真眼  阅读(126)  评论(0编辑  收藏  举报