pku3411 Paid Roads 搜索 + 剪枝

Paid Roads

题很简单,但是需要些剪枝技巧,我的做法是,先不管Pi,直接用dijkstra,求得1到N的最短距离,作为搜索上界或次优解,再用深搜,对边搜索,求得最优解,刚开始没有求上界的时候TLE,加了以后0ms AC。看来剪枝很重要。

ContractedBlock.gif ExpandedBlockStart.gif 代码
 
   
1 /* 搜索 + 剪枝,有的边可能经过两次 */
2 #include < stdio.h >
3 #include < string .h >
4   #define INF 1000
5 #define NN 12
6 int N, m, ans;
7 int a[ 12 ], b[ 12 ], c[ 12 ], p[ 12 ], r[ 12 ];
8 int vis[ 12 ];
9
10 char mark[NN];
11 int map[NN][NN];
12 int dis[NN];
13 void dijkstra( int t) // t表示源点
14 {
15 int i, j, min, key, num;
16 for (i = 1 ; i <= N; i ++ )
17 dis[i] = map[t][i];
18 mark[t] = 1 ;
19 num = N - 1 ;
20 while (num -- )
21 {
22 min = INF + 1 ; // 容易出错
23 key = 0 ;
24 for (i = 1 ; i <= N; i ++ )
25 if ( ! mark[i] && dis[i] < min)
26 {
27 min = dis[i];
28 key = i;
29 }
30 mark[key] = 1 ;
31 for (j = 1 ; j <= N; j ++ )
32 if ( ! mark[j] && dis[key] + map[key][j] < dis[j])
33 dis[j] = dis[key] + map[key][j];
34 }
35 }
36
37
38 void dfs( int cur, int sum){
39 // printf("%d %d\n", cur, sum);
40 if (sum >= ans) return ;
41 if (cur == N){
42 ans = sum;
43 return ;
44 }
45
46 int i;
47 for (i = 1 ; i <= m; i ++ ){
48 if (a[i] == cur){
49 vis[b[i]] += 1 ;
50 if (vis[c[i]] && p[i] < r[i]){
51 dfs(b[i], sum + p[i]);
52 } else {
53 dfs(b[i], sum + r[i]);
54 }
55 vis[b[i]] -= 1 ;
56 }
57 }
58 }
59 int main()
60 {
61 int i, j;
62 scanf( " %d%d " , & N, & m);
63 for (i = 1 ; i <= N; i ++ ){
64 for (j = 1 ; j <= N; j ++ ){
65 if (i == j) map[i][j] = 0 ;
66 else map[i][j] = INF;
67 }
68 }
69 for (i = 1 ; i <= m; i ++ ){
70 scanf( " %d%d%d%d%d " , & a[i], & b[i], & c[i], & p[i], & r[i]);
71 if (r[i] < map[a[i]][b[i]]) map[a[i]][b[i]] = r[i];
72 }
73 dijkstra( 1 );
74 if (dis[N] == INF){
75 puts( " impossible " );
76 return 0 ;
77 }
78 memset(vis, 0 , sizeof (vis));
79 vis[ 1 ] = 1 ;
80 ans = dis[N];
81 dfs( 1 , 0 );
82 printf( " %d\n " , ans);
83 return 0 ;
84 }
85 /*
86 6 5
87 1 2 1 10 10
88 2 3 4 10 100
89 2 4 2 15 15
90 4 1 1 12 12
91 3 6 6 10 10
92
93 ans: 67 */
94

 

转载于:https://www.cnblogs.com/ylfdrib/archive/2010/09/06/1819618.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值