随笔 - 19, 文章 - 0, 评论 - 2, 引用 - 0
数据加载中……

zoj2504_Help John!

          这一题仍然是最短路径,一次AC!好高兴啊。题目是单纯的最短路径的小变形,只要从妈妈说的第二个路口开始找最短路径开始就可以了。

#include <stdio.h>
#define DEBUG 1

const int N=1111 ;
const int Max=0xfffffff ;
int n, sum, map[N][N], dis[N], used[N], mo[30002] ;

void Dijstra( )
{
    
int i, j, index, min ;
    
for( i=1; i<=n; ++i ){
        
//从第二个路口开始找最短路径,因为,第一个
        
//路口是必须走的,因为妈妈看着我呢! 
        dis[i] = map[mo[2]][i] ;
        used[i] 
= 0 ;
    }

    used[
1= 1 ;
    used[mo[
2]] = 1 ;
    
for( i=1; i<=n; ++i ){
        min 
= Max ;
        
for( j=1; j<=n; ++j ){
            
if!used[j] && min>dis[j] ){
                index 
= j ;
                min 
= dis[j] ;
            }

        }

        used[index] 
= 1 ;
        
for( j=1; j<=n; ++j )
            
if!used[j] && dis[j] > dis[index]+map[index][j] )
                dis[j] 
= dis[index]+map[index][j] ;
    }

    
//计算差值 
    printf("Y %d\n", sum-dis[n] ) ;
}


int main()
{
    
#if DEBUG
     freopen(
"C:\\Documents and Settings\\Administrator\\桌面\\in.txt","r",stdin);
     freopen(
"C:\\Documents and Settings\\Administrator\\桌面\\out.txt","w",stdout);
     
#endif
     
     
int i, j, k, r, di, flag, x, y, sets, mother ;
     scanf(
"%d"&sets ) ;
     
for( k=1; k<=sets; ++k ){
        printf(
"TEST %d ", k ) ;
        scanf(
"%d%d"&n, &r ) ;
        
for( i=1; i<=n; ++i ){
            
for( j=1; j<=n; ++j )
                map[i][j] 
= Max ;
            map[i][i] 
= 0 ;
        }
    
        
for( i=1; i<=r; ++i ){
            scanf(
"%d%d%d"&x, &y, &di ) ;
            map[x][y] 
= map[y][x] = di ;
        }

        scanf(
"%d"&mother ) ;
        
for( i=1; i<=mother; ++i )
            scanf(
"%d"&mo[i] ) ;
        sum 
= flag = 0 ;
        
//妈妈说第一条路必须走,因为她说她在看着我
        
//但是最后还是要减掉的,所以要走,但是不加上。
        for( i=2; i<mother; ++i ){
            
//如果没路,就输出 N !妈妈和我开玩笑呢!
            
// 继续下一次读入信息 
            if( map[mo[i]][mo[i+1]] == Max ){
                printf(
"N\n") ;
                flag 
= 1 ;
                
break ;
            }

            
//按照妈妈说的路线走,看看要走多远 
            sum += map[mo[i]][mo[i+1]] ;
        }

        
if!flag )
            Dijstra( ) ;    
    }

    
return 0 ;
}

posted @ 2009-05-07 21:13 祝你好运! 阅读(109) | 评论 (0)编辑 收藏

hdu1162_Eddy's picture

        题目就是给出一个笛卡尔坐标系,然后给出一些点,问题就是要求最小生成树。我以前没有做过这样的,因为这里,一个点到另一个点的距离没有给出。难道要把一个点到所有的点的距离都求出来?那样的话时间复杂度就太高了吧?
        我发现我现在还是太贪求速度,我确实是想到了这里,但是我没有去做,去写,而是去找别人的代码,先看看别人是怎么写的,然后我再写。其实,他们和我的算法思想是一样的。我以后要尽力改正这一个不好的习惯。这样非常不利于我学习算法。加油!

#include <stdio.h>
#include 
<math.h>
#define DEBUG 1
const double Max = 0x7fffffff ;
const int N = 111 ;
int n, used[N], closest[N] ;
double map[N][N], pos[N][2], dis[N] ;

double Distance( double *a, double *b )
{
    
return sqrt( (a[0]-b[0])*(a[0]-b[0]) + (a[1]-b[1])*(a[1]-b[1]) ) ;
}


double Prim( )
{
    
int i, j, index ;
    
double min, len ;
    
for( i=1; i<=n; ++i ){
        used[i] 
= 0 ;
        dis[i] 
= map[1][i] ;
    }

    used[
1= 1 ;
    len 
= 0 ;
    
for( i=1; i<n; ++i ){
        min 
= Max ;
        
for( j=1; j<=n; ++j ){
            
if!used[j] && min>dis[j] ){
                index 
= j ;
                min 
= dis[j] ;
            }

        }

        used[index] 
= 1 ;
        len 
+= dis[index] ;
        
for( j=1; j<=n; ++j ){
            
if!used[j] && dis[j]>map[j][index] )
                dis[j] 
= map[j][index] ;
        }

    }

    
return len ;    
}


int main()
{
    
#if DEBUG
     freopen(
"C:\\Documents and Settings\\Administrator\\桌面\\in.txt","r",stdin);
     freopen(
"C:\\Documents and Settings\\Administrator\\桌面\\out.txt","w",stdout);
     
#endif
     
    
int i, j ;
    
while( EOF != scanf("%d"&n ) ){
        
for( i=1; i<=n; ++i )
            
for( j=1; j<=n; ++j )
                map[i][j] 
= Max ;
        
for( i=1; i<=n; ++i )
            scanf(
"%lf%lf"&pos[i][0], &pos[i][1] ) ;
        
for( i=1; i<=n; ++i ){
            
for( j=i+1; j<=n; ++j ){
                map[i][j] 
= map[j][i] = Distance( pos[i], pos[j] ) ;
            }

        }

        printf(
"%.2lf\n", Prim( ) ) ;
    }

    
return 0 ;
}

posted @ 2009-05-05 17:08 祝你好运! 阅读(238) | 评论 (0)编辑 收藏

hdu1102_Constructing Roads

        虽然这一题已经写过了,但是我觉得这里有问题。因为题目中有这样的一句话:
        We say two village A and B are connected, if and only if there is a road between A and B, or there exists a village C such that there is a road between A and C, and C and B are connected.
        这样一来,如果是A-B-C-D,我们能说A和D是相通的吗?我觉得不能,但是参考别人的代码时,他们都没有考虑这一中情况,我也写了一个没有考虑的。竟然过了!不知道为什么。我主要是在练习算法,难道是我理解错了?

#include <stdio.h>
#define DEBUG 1
const int Max = 0x7fffffff ;
const int N = 111 ;
int n, dis[N], used[N], closest[N], map[N][N] ;

int Prim( )
{
    
int i, j, index, min, len ;
    
for( i=1; i<=n; ++i ){
        used[i] 
= 0 ;
        dis[i] 
= map[1][i] ;
    }

    used[
1= 1 ;
    len 
= 0 ;
    
for( i=1; i<n; ++i ){
        min 
= Max ;
        
for( j=1; j<=n; ++j ){
            
if!used[j] && min>dis[j] ){
                index 
= j ;
                min 
= dis[j] ;
            }

        }

        used[index] 
= 1 ;
        len 
+= dis[index] ;
        
for( j=1; j<=n; ++j ){
            
if!used[j] && dis[j]>map[j][index] )
                dis[j] 
= map[j][index] ;
        }

    }

    
return len ;
}

int main()
{
    
#if DEBUG
     freopen(
"C:\\Documents and Settings\\Administrator\\桌面\\in.txt","r",stdin);
     freopen(
"C:\\Documents and Settings\\Administrator\\桌面\\out.txt","w",stdout);
     
#endif
     
    
int i, j, x, y, comp ;
    
while( EOF != scanf("%d"&n ) && n ){
        
for( i=1; i<=n; ++i ){
            
for( j=1; j<=n; ++j ){
                scanf(
"%d"&map[i][j] ) ;
                map[j][i] 
= map[i][j] ;
            }

        }

        scanf(
"%d"&comp ) ;
        
for( i=1; i<=comp; ++i ){
            scanf(
"%d%d"&x, &y ) ;
            map[x][y] 
= map[y][x] = 0 ;
        }

        printf(
"%d\n", Prim( ) ) ;
    }
                    
    
return 0 ;
}

posted @ 2009-05-05 15:26 祝你好运! 阅读(265) | 评论 (1)编辑 收藏

hdu1233_还是畅通工程

          没什么好说的,还是最小生成树,和上一题一样,没有任何变化。我现在只会prim算法,所以就只用prim写。

#include <stdio.h>
#define DEBUG 1
const int N=101 ;
const int Max = 0x7fffffff ;
int n, map[N][N], dis[N], used[N], closest[N] ;

int Prim( )
{
    
int i, j, index, min, len ;
    len 
= 0 ;
    
    
for( i=1; i<=n; ++i ){
        dis[i] 
= map[1][i] ;
        used[i] 
= 0 ;
        closest[i] 
= 1 ;
    }

     used[
1= 1 ;
     
for( i=1; i<n; ++i ){    
         min 
= Max ;
          
for( j=1; j<=n; ++j ){
              
if!used[j] && min>dis[j] ){
                  min 
= dis[j] ;
                  index 
= j ;
              }

        }

        used[index] 
= 1 ;
        len 
+= dis[index] ;
        
for( j=1; j<=n; ++j ){
            
if!used[j] && dis[j]>map[index][j] ){
                closest[j] 
= index ;
                dis[j] 
= map[index][j] ;
            }

        }

    }

    
return len ;            
}


int main()
{
    
#if DEBUG
    freopen(
"C:\\Documents and Settings\\Administrator\\桌面\\in.in","r",stdin) ;
    freopen(
"C:\\Documents and Settings\\Administrator\\桌面\\out.out","w",stdout) ;
    
#endif
    
    
int i, j, x, y, weight, hangshu ;
    
while( scanf("%d"&n) && n ){
        
for( i=1; i<=n; ++i ){
            
for( j=1; j<=n; ++j ){
                map[i][j] 
= Max ;
            }

        }

        hangshu 
= n*(n-1)/2 ;
        
for( i=1; i<=hangshu; ++i ){
            scanf(
"%d%d%d"&x, &y, &weight ) ;
            map[x][y] 
= map[y][x] = weight ;
        }

        printf(
"%d\n", Prim( ) ) ;
    }
    
    
return 0 ;
}
 

posted @ 2009-05-05 01:26 祝你好运! 阅读(440) | 评论 (0)编辑 收藏

hdu1301_Jungle Roads

        这是我做的第一个最小生成树的题目。算法思想就是从任意一个点出发,标记为已找到的。然后找到所有与已找到的点相连的边中,权值最小的边。把边的另一个顶点标记为已找到的。然后更新所有与这个刚找到的顶点相邻的顶点的信息。重复这个步骤,直到找到了n-1个顶点。那就组成了一棵最小生成树,就是题目结束了。
#include <stdio.h>
#define DEBUG 1
const int Max = 0x7fffffff ;
const int N = 30 ;
int n, map[N][N], dis[N], used[N] ;

int Prim( )
{
    
int i, j, index, len, min ;
    len 
= 0 ;
    
for( i=1; i<=n; ++i ){
        
// 出发点定义为 1 
        dis[i] = map[1][i] ;
        used[i] 
= 0 ;
    }

    
// used[]数组作为标志 ,表示已经被标记过的点 
    used[1= 1 ;
    
for( i=1; i<n; ++i ){
        min 
= Max ;
        
//找到所有与已标记过的点相连的边中,权值最小的边 
        for( j=1; j<=n; ++j ){
            
if!used[j] && min>dis[j] ){
                index 
= j ;
                min 
= dis[j] ;
            }

        }

        used[index] 
= 1 ;
        len 
+= dis[index] ;
        
//更新所有与已找到的点相连的边的信息 
        for( j=1; j<=n; ++j ){
            
if!used[j] && dis[j]>map[index][j] )
                dis[j] 
= map[index][j] ;
        }

    }

    
return len ;           
}


int main()
{
    
//输入输出的重定向 
    #if DEBUG
    freopen(
"C:\\Documents and Settings\\Administrator\\桌面\\in.in","r",stdin) ;
    freopen(
"C:\\Documents and Settings\\Administrator\\桌面\\out.out","w",stdout) ;
    
#endif
    
    
int i, j, d, geshu, weight ;
    
char ch, to ;
    
while( scanf("%d"&n) && n ){
        
//初始化数据 
        for( i=1; i<=n; ++i ){
            
for( j=1; j<=n; ++j ){
                map[i][j] 
= Max ;
            }

        }

        
//读入数据 
        for( i=1; i<n; ++i ){
            
//吃掉空格,不然机会造成读入数据错误 
            getchar() ;
            scanf(
"%c %d"&ch, &geshu ) ;
            
for( j=1; j<=geshu; ++j ){
                scanf(
" %c %d"&to, &weight ) ;
                
// -64 是为了把第一个点,也就是A点,当成第一个点
                 
// 因为A的ASCII是65 ,所以65-64 就是 1
                 
// 建立的是无向图 
                map[i][to-64= map[to-64][i] = weight ;
               }

        }

        printf(
"%d\n", Prim( ) ) ;
    }

    
return 0 ;
}

posted @ 2009-05-05 00:39 祝你好运! 阅读(212) | 评论 (0)编辑 收藏

hdu1548 A strange lift

         又是一道典型的最短路径的题目,当然也可以用搜索,我现在在学习最短路径,所以就用Dijsktra来做的,一开始时WA了好几次,是因为这一题是应该抽象出来一个有向图,而我却是用了无向图,所以一直WA。最后改了一下,然后就过了。

#include <stdio.h>
#define DEBUG 1
const int N=300 ;
const int Max = 10000000 ;
int n, map[N][N], used[N], dis[N] ;

void Dijkstra( int a, int b )
{
    
int i, j, index, min ;
    
for( i=1; i<=n; ++i ){
        dis[i] 
= map[a][i] ;
        used[i] 
= 0 ;
    }

    used[a] 
= 1 ;
    
for( i=1; i<=n; ++i ){
        index 
= a ;
        min 
= Max ;
        
for( j=1; j<=n; ++j ){
               
if!used[j] && min > dis[j] ){
                   min 
= dis[j] ;
                   index 
= j ;
             }

        }

        used[index] 
= 1 ;
        
for( j=1; j<=n; ++j ){
            
if( dis[j] > dis[index]+map[index][j] )
                dis[j] 
= dis[index]+map[index][j] ;
        }

    }

    
if( dis[b] == Max ){
        
//printf("%d\n", dis[b] ) ;
        printf("-1\n") ;
    }
       
    
else
        printf(
"%d\n", dis[b] ) ;
}


int main( )
{
    
#if DEBUG
    freopen(
"C:\\Documents and Settings\\Administrator\\桌面\\in.in","r",stdin) ;
    freopen(
"C:\\Documents and Settings\\Administrator\\桌面\\out.out","w",stdout) ;
    
#endif
    
    
int i, j, a, b, temp ;
    
while( scanf("%d"&n) && n ){
        
for( i=1; i<=n; ++i ){
               
for( j=1; j<=n; ++j )
                   map[i][j] 
= Max ;
               map[i][i] 
= 0 ;    
        }

        scanf(
"%d%d"&a, &b ) ;
        
for( i=1; i<=n; ++i ){
            scanf(
"%d"&temp ) ;
            
if( i - temp > 0 )
                map[i][i
-temp] = 1 ;
            
if( i + temp <= n )
                 map[i][i
+temp] = 1 ;
        }

        Dijkstra( a, b ) ;
    }
         
    
return 0 ;
}

posted @ 2009-05-03 21:16 祝你好运! 阅读(356) | 评论 (0)编辑 收藏

hdu1548_A strange lift

#include <stdio.h>
#define DEBUG 1
const int N=300 ;
const int Max = 10000000 ;
int n, map[N][N], used[N], dis[N] ;

void Dijkstra( int a, int b )
{
    
int i, j, index, min ;
    
for( i=1; i<=n; ++i ){
        dis[i] 
= map[a][i] ;
        used[i] 
= 0 ;
    }

    used[a] 
= 1 ;
    
for( i=1; i<=n; ++i ){
        index 
= a ;
        min 
= Max ;
        
for( j=1; j<=n; ++j ){
               
if!used[j] && min > dis[j] ){
                   min 
= dis[j] ;
                   index 
= j ;
             }

        }

        used[index] 
= 1 ;
        
for( j=1; j<=n; ++j ){
            
if( dis[j] > dis[index]+map[index][j] )
                dis[j] 
= dis[index]+map[index][j] ;
        }

    }

    
if( dis[b] == Max ){
        
//printf("%d\n", dis[b] ) ;
        printf("-1\n") ;
    }
       
    
else
        printf(
"%d\n", dis[b] ) ;
}


int main( )
{
    
#if DEBUG
    freopen(
"C:\\Documents and Settings\\Administrator\\桌面\\in.in","r",stdin) ;
    freopen(
"C:\\Documents and Settings\\Administrator\\桌面\\out.out","w",stdout) ;
    
#endif
    
    
int i, j, a, b, temp ;
    
while( scanf("%d"&n) && n ){
        
for( i=1; i<=n; ++i ){
               
for( j=1; j<=n; ++j )
                   map[i][j] 
= Max ;
               map[i][i] 
= 0 ;    
        }

        scanf(
"%d%d"&a, &b ) ;
        
for( i=1; i<=n; ++i ){
            scanf(
"%d"&temp ) ;
            
if( i - temp > 0 )
                map[i][i
-temp] = 1 ;
            
if( i + temp <= n )
                 map[i][i
+temp] = 1 ;
        }

        Dijkstra( a, b ) ;
    }
         
    
return 0 ;
}

posted @ 2009-05-03 21:10 祝你好运! 阅读(166) | 评论 (0)编辑 收藏

杭电1142 A Walk Through the Forest

        这一星期我在学习单源最短路径,今天是这一星期的最后一天。我半写半参考的写出了这一题,要用到DFS+Dijsktra。

        题目是让求一个点到另一个点的“前进的”(就是越走离家越近,这是一个难点,不然就做不出来)路径的条数。算法思想是:先求出家到每一个顶点的最短路径,然后用深搜求出从公司到家的路径的条数。

 

#include <stdio.h>
#include 
<memory.h>
#define debug 1
#define N 1010
//要注意不要把Max定义的太大,不然会在做加法时溢出,
// 当然,要是不做加法,就没事了,可以定义为2147483647
//也可以用 __int64 ,但是那样的效率比较低 
#define Max 10000000

int n ;
int map[N][N], dis[N], used[N], num[N] ;

void Input( )
{
    
int i, j, x, m, y, distance ;
    
for( i=1; i<=n; ++i ){
        
for( j=1; j<=n; ++j ){
            map[i][j] 
= Max ;
        }

        
//自己到自己的最短路径是0 
        map[i][i] = 0 ;
    }
    
    scanf(
"%d"&m ) ; 
    
for( i=0; i<m; ++i ){
        scanf(
"%d%d%d"&x, &y, &distance ) ;
        
//用无向图来存储数据 
        map[x][y] = distance ;
        map[y][x] 
= distance ;
    }
    
}


void Dijstra( int v )
{
    
int i, j, min, index ;
    
for( i=1; i<=n; ++i ){
        
//求家到各个顶点的初始路径的距离,如果没有路径,就是Max 
        dis[i] = map[v][i] ;
        
//用来标记是否已经求过 
        used[i] = 0 ;
    }

    
// 从家里出发,家已经走过,标记为1,下同 
    used[v] = 1 ;
    
for( i=1; i<=n; ++i ){
        min 
= Max ;
        index 
= v ;
        
//找到与每一个已标记过的顶点之间距离最小的顶点 
        for( j=1; j<=n; ++j ){
            
if!used[j] && min > dis[j] ){
                index 
= j ;
                min 
= dis[j] ;
            }

        }

        
//已经找到,标记 
        used[index] = 1 ;
        
//更新与刚找到的顶点相邻的顶点的最短路径 
        for( j=1; j<=n; ++j ){
            
if( dis[j] > dis[index] + map[index][j] )
                dis[j] 
= dis[index] + map[index][j] ;
        }

    }
           
}


int DFS( int nod )
{
    
int i, count ;
    
//如果已到家,就返回1,表示找到了一条路 
    if( nod == 2 )
        
return 1 ;
    
//如果这一点已经求过,就返回这一点到家的路径的条数    
    if( num[nod] > 0 )
        
return num[nod] ;    
    count 
= 0 ;
    
//对每一个顶点进行判断,并求路径的条数 
    for( i=1; i<=n; ++i ){
        
if( map[i][nod]<Max && dis[i]<dis[nod] )
            count 
+= DFS( i ) ;
    }

    
//标记路径的条数,并返回值 
    num[nod] = count ;
    
return count ;        
}


int main()
{
    
// 输入输出的重定向,便于调试,在提交时要把debug改成0 
    #if debug
    freopen(
"C:\\Documents and Settings\\Administrator\\桌面\\in.in","r",stdin) ;
    freopen(
"C:\\Documents and Settings\\Administrator\\桌面\\out.out","w",stdout) ;
    
#endif
    
    
while( scanf("%d",&n) && n ){
        
//读入数据 
        Input( ) ;
        
//调用Dijsktra 求家到每一个节点的最短路径 
        Dijstra( 2 ) ;
        
// 数据初始化 
        memset( num, 0sizeof(num) ) ;
        
// 用深搜求的路径的条数 
        printf("%d\n", DFS( 1 ) ) ; 
    }
        
    
return 0 ;
}

posted @ 2009-05-03 17:35 祝你好运! 阅读(461) | 评论 (1)编辑 收藏

杭电1398

#include <iostream>
using namespace std;
const int lmax=10000;
//c1是用来存放展开式的系数的,而c2则是用来计算时保存的,
//他是用下标来控制每一项的位置,比如 c2[3] 就是 x^3 的系数。 
//用c1保存,然后在计算时用c2来保存变化的值。 
int c1[lmax+1],c2[lmax+1];
int main()
{
    
int n, i, j, k ;
    
// 计算的方法还是模拟手动运算,一个括号一个括号的计算,
    
// 从前往后 
    while ( cin>>n ){
        
//对于 1+x+x^2+x^3+ 他们所有的系数都是 1  
        
// 而 c2全部被初始化为0是因为以后要用到 c2[i] += x ; 
        for ( i=0; i<=n; i++ ){
            c1[i]
=1;
            c2[i]
=0;
           }

           
//第一层循环是一共有 n 个小括号,而刚才已经算过一个了
        
//所以是从2 到 n  
        for (i=2; i<=n; i++){
            
// 第二层循环是把每一个小括号里面的每一项,都要与前一个
              
//小括号里面的每一项计算。 
               for ( j=0; j<=n; j++ )
                   
//第三层小括号是要控制每一项里面 X 增加的比例 
                   
// 这就是为什么要用 k+= i ; 
                for ( k=0; k+j<=n; k+=i ){
                    
// 合并同类项,他们的系数要加在一起,所以是加法,呵呵。 
                    
// 刚开始看的时候就卡在这里了。 
                    c2[j+k] += c1[j];
                }

            
// 刷新一下数据,继续下一次计算,就是下一个括号里面的每一项。    
            for ( j=0; j<=n; j++ ){
                c1[j] 
= c2[j] ;
                c2[j] 
= 0 ;
            }

        }

        cout
<<c1[n]<<endl;
   }

   
return 0;
}

posted @ 2009-04-29 10:47 祝你好运! 阅读(203) | 评论 (0)编辑 收藏

仅列出标题
共2页: 1 2