zoukankan      html  css  js  c++  java
  • 8月12号的最短路:POJ 1062&&HDU 1317

    下面是算是难的了吧。。。(不知道还搞得掉吗!)

    先上这个。。。

                                                                               昂贵的聘礼  POJ 1062

    最近比较浮躁。看了好久才懂的。。。

    首先题已经知道起点!限制条件:因为有等级制度的限制。可用枚举(一个一个物品列出来)

    之后发现是单向图问题!

    先看代码吧。

     1 #include<iostream>
     2 #include<stdio.h>
     3 #include<algorithm>
     4 using namespace std;
     5 int max1,a[105][105],level[105],d[105],m,vis[105];
     6 int distesila()
     7 {
     8     int i,min1,j,p;
     9     for(i=1;i<=m;i++)
    10         d[i]=a[0][i];
    11     for(i=1;i<=m;i++)
    12     {
    13         min1=1000005;
    14         for(j=1;j<=m;j++)
    15             if(!vis[j]&&d[j]<min1)
    16             {
    17                 min1=d[j];
    18                 p=j;
    19             }
    20         vis[p]=1;//并巧妙地和该算法已有的数组结合起来
    21         for(j=1;j<=m;j++)
    22         {
    23             if(!vis[j]&&d[j]>d[p]+a[p][j])
    24                 d[j]=a[p][j]+d[p];
    25         }
    26     }
    27     return d[1];
    28 }
    29 int main()
    30 {
    31     int max1,max2,n,i,j,p,a1,a2,b2,min1level,sd;
    32     max1=10000005;
    33     while(scanf("%d%d",&n,&m)!=EOF)
    34     {
    35         for(i=0;i<=m;i++)
    36             for(j=0;j<=m;j++)
    37                 a[i][j]=max1;
    38         for(i=0;i<=m;i++)
    39             a[i][i]=0;
    40         for(i=1;i<=m;i++)
    41         {
    42             scanf("%d%d%d",&p,&level[i],&a1);
    43             while(a1--)
    44             {
    45                 scanf("%d%d",&a2,&b2);
    46                 a[a2][i]=b2;
    47             }
    48             a[0][i]=p;//既然题目中没有明确的起点且值不会小于1的,就标志为0了
    49         }
    50         max2=100005;
    51         for(i=1;i<=m;i++)
    52         {
    53             min1level=level[i];//假定为最小的进行枚举
    54             for(j=1;j<=m;j++)
    55         {
    56             if(level[j]-min1level>n||level[j]<min1level)
    57                 vis[j]=1;//判断并用数组进行储存该情况
    58             else
    59                 vis[j]=0;
    60         }
    61         sd=distesila();
    62         max2=min(max2,sd);
    63         }//此处用枚举把每种可能算出来,取最小值
    64         printf("%d
    ",max2);
    65     }
    66     return 0;
    67 }

     经过三天的洗礼:终于看懂了。。。(!!!)

                                                    XYZZY  HDU 1317

    先讲一下题意:

    有n个房间,编号1~n,小明要从1走到n。

    接下给出n排:

    第一个数 :到达此房间可获得的能量(100~-100) 岔口数(与哪些房间相连) 编号

    注意:起点与终点获得的能量为0.初始能量为100.且每个房间只能获得一次。

    因为还不知道什么是正环和负环。。。(相对于最长路与最短路来说)

    首先这个题目应该求最长路吧。。。(到终点能量为正啊)

    那么对应的正环就出现了,(谁会想到一开始判断1到n是否有房间连接。。。)

    但是出现了正环的话,表示着什么呢?

    反正求最短路时,还没遇到值为负的。。。就不清楚负环的含义。。。

    看了百度百科才发现出现负环表明无最短路径。。。条件是:某点进入队列超过n次!

    那么对应的正环一旦出现的话,能量对应的就为很大很大了。。。之后就判断此点到终点能不能有房间联通就行了。。。此刻就需要上面没有想到的(谁会想到一开始判断1到n是否有房间连接。。。)

    那么就顺便在一开始判断1到n是否有房间连接。。。

    那么关键还是理解spfa算法和负环。。。

     1 #include<iostream>
     2 #include<queue>
     3 #include<string.h>
     4 #include<algorithm>
     5 #include<stdio.h>
     6 const int MAXN=110;
     7 using namespace std;
     8 int n;
     9 int weight[MAXN];
    10 int power[MAXN];
    11 int _count[MAXN];//记录某点的入队列次数
    12 bool map[MAXN][MAXN];//区分于reach[]的用法
    13 bool reach[MAXN][MAXN];//floyd判断任何两点是否可达
    14 
    15 
    16 void Floyd()
    17 {
    18     for(int k=1;k<=n;k++)
    19         for(int i=1;i<=n;i++)
    20             for(int j=1;j<=n;j++)
    21                 reach[i][j]=(reach[i][j]||(reach[i][k]&&reach[k][j]));
    22 }
    23 
    24 bool SPFA(int now)
    25 {
    26     queue<int>Q;
    27     Q.push(now);
    28     memset(power,0,sizeof(power));
    29     memset(_count,0,sizeof(_count));
    30     power[1]=100;
    31     while(!Q.empty())
    32     {
    33         int now=Q.front();
    34         Q.pop();
    35         _count[now]++;
    36         if(_count[now]>=n)
    37             return reach[now][n];//如果某个点的次数超过n次,那么说明存在正环,此时只要判断这点到n点是否可达就行了
    38         for(int next=1;next<=n;next++)
    39             if(map[now][next]&&power[now]+weight[next]>power[next]&&power[now]+weight[next]>0)//避免有负数
    40             {
    41                 Q.push(next);
    42                 power[next]=power[now]+weight[next];
    43             }
    44     }
    45     return power[n]>0;
    46 }//这里少了一个判断是否入列的数组,但没关系,不过时间较长一些
    47 
    48 int main()
    49 {
    50     while(~scanf("%d",&n)&&n!=-1)
    51     {
    52         memset(map,false,sizeof(map));
    53         memset(reach,false,sizeof(reach));
    54         for(int i=1;i<=n;i++)
    55         {
    56             int num;
    57             scanf("%d%d",&weight[i],&num);
    58             while(num--)
    59             {
    60                 int k;
    61                 scanf("%d",&k);
    62                 map[i][k]=true;
    63                 reach[i][k]=true;
    64             }
    65         }
    66         Floyd();
    67         if(!reach[1][n])//如果起点到终点没有房间连接
    68             printf("hopeless
    ");
    69         else
    70         {
    71             if(SPFA(1))
    72                 printf("winnable
    ");
    73             else
    74                 printf("hopeless
    ");
    75         }
    76     }
    77     return 0;
    78 }
  • 相关阅读:
    java反射详解
    Oracle创建视图权限不足(解决)
    SQL Server为啥使用了这么多内存?
    在cmd中运行android.bat报出空指针异常
    QTP生成随机数字+字母
    loadView和ViewDidLoad区别
    Bonjour(苹果电脑公司的服务器搜索协议商标名)
    |= 或赋值
    我见过的类
    UML 继承和接口实现
  • 原文地址:https://www.cnblogs.com/tt123/p/3255882.html
Copyright © 2011-2022 走看看