uva 11280 状态压缩+最短路

题意:坐飞机从 a 地到 b 地 ,在最多停留s次时 , 最小花费是多少?

在题目给出的地点 , 是按从远到近给出的 , 并且给出的航班中 , 不会有从远地点到近地点的航班。

因此从这可以看出 , 题目给的图是一个DAG图 , 那么我们就能用toposort来找最短路。

注意: 会有重边

解法:

构造一个数组 d[i][j]  , 表示从开始点 s  到点 i , 在停留 j 次时的最小花费。

然后我们再求出这个图的toposort , 再求这个每一个点和其相邻点的距离。

代码:

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <vector>
#include <queue>
#include <map>

using namespace std;

#define maxn 110
#define INF 0xfffffff

int grap[maxn][maxn] ;
long long d[maxn][maxn];
int n , m;
int s1 , t1;
int s;
int index1[maxn];  //存储每个点的入度
int topo[maxn];

void init()
{
    memset(grap , -1 , sizeof(grap));
    memset(index1 , 0 , sizeof(index1));
    s1 = 0 , t1 = n-1;
    s = n-2;
}
//可能会有重边

void add_edge(int x , int y , int z)
{
    if(grap[x][y] == -1)
    {
        grap[x][y] = z;
        index1[y] += 1;
    }
    else if(grap[x][y] > z)
        grap[x][y] = z;
}

void toposort()
{
    int i , u;
    int l = 0 , r = 0;
    for(i = 0; i < n; i++)
        if(index1[i] == 0)  topo[r++] = i;
    while(l < r)
    {
        u = topo[l++];
        for(i = 0; i < n; i++)
            if(grap[u][i] != -1 && index1[i] > 0)
            {
                index1[i]--;
                if(index1[i] == 0)
                    topo[r++] = i;
            }
    }
}

void spfa()
{
    int i , j;
    int u , v;
    for(i = 0; i < n; i++)
        for(j = 0; j <= s; j++)
            d[i][j] = INF;
    for(i = 0; i < n; i++)
        if(grap[s1][i] != -1)
            d[i][0] = grap[s1][i];

    j = 1;
    while(j < n)
    {
        u = topo[j];
        for(v = 0; v < s; v++)
        {
            if(d[u][v] == INF)  continue;
            for(i = 0; i < n; i++)
                if(grap[u][i] != -1)
                {
                    if(d[i][v+1] > d[u][v]+grap[u][i])
                    {
                        d[i][v+1] = d[u][v]+grap[u][i];
                    }
                }
        }
        j++;
    }
}

int main()
{
    //用map来区分每个点
    //cout<<INF<<endl;
    int t , cas = 1;
    scanf("%d" , &t);
    while(t--)
    {
        scanf("%d" , &n);
        init();
        map<string , int>ma;
        char city[30] , city2[30];
        int i , x , y , z;
        for(i = 0; i < n; i++)
        {
            scanf("%s" , city);
            ma[city] = i;
        }
        map<string,int>::iterator it;
        scanf("%d" , &m);
        for(i = 0; i < m ; i++)
        {
            scanf("%s %s %d" , city , city2 , &z);
            it=ma.find(city);
            x = it->second;
            it=ma.find(city2);
            y = it->second;
            add_edge(x , y , z);
        }
        int q;
        toposort();
        spfa();
        for(i = 1; i <= s; i++)
            d[t1][i]  = min(d[t1][i] , d[t1][i-1]);

        scanf("%d" , &q);
        printf("Scenario #%d\n" , cas++);
        for(i = 0; i < q; i++)
        {
            scanf("%d" , &x);
            x = x>s?s:x;
            if(d[t1][x] == INF)  cout<<"No satisfactory flights"<<endl;
            else  cout<<"Total cost of flight(s) is $"<<d[t1][x]<<endl;
        }
        if(t) cout<<endl;
    }

    return 0;
}
/*
2
4
Calgary
Winnipeg
Ottawa
Fredericton
7
Calgary Ottawa 350
Calgary Winnipeg 125
Calgary Ottawa 300
Winnipeg Fredericton 325
Winnipeg Ottawa 100
Calgary Fredericton 875
Ottawa Fredericton 175
3 2 1 0
3
Calgary
Montreal
Fredericton
2
Calgary Montreal 300
Montreal Fredericton 325
1 0
*/

uva 11280 状态压缩+最短路

时间: 2024-10-25 06:21:31

uva 11280 状态压缩+最短路的相关文章

uva 10817 状态压缩DP

题意: 有S个课程要教, 学校本来有m个教师 给出工资和所教课程编号  (在职教师不能辞退) 来应聘的有n个教师 给出工资和所教课程编号 问保证每个课程都有两个老师可以教的前提下,最少发多少工资 思路: 水题: 总共最多只有8个课程,状态压缩 d[i][s1][s2] 表示当前状态下,有一个老师教的课程是s1,有两个或两个人以上教的课程是s2 转移就是当前教师选或不选,对应的转移到下一个(i+1个)教师的决策即可. code: #include<cstdio> #include<iost

uva 1252(状态压缩dp)

题意:有n个二进制串,长度都是m且都不相同,问最少询问多少个问题可以把这n个串完全区分开. 题解:1<=m<=11,从这个范围就可以推测是状态压缩,那么dp肯定要有一维表示提问的问题,然后另一位就是根据提出的问题把串分类,一种是符合提出的问题的状态,另一种不符合.这样f[i][j]表示在问了问题i的状态下答案是状态j时还要提出多少个问题才能把所有串区分开. 如果找到在问题i下和答案j相同的串只有1串或没有,说明f[i][j]=0不需要再提问就已经区分开了,否则就要再提问问题,把之前问题i的位上

UVA 11825 状态压缩DP+子集思想

很明显的状态压缩思想了.把全集分组,枚举每个集合的子集,看一个子集是否能覆盖所有的点,若能,则f[s]=max(f[s],f[s^s0]+1).即与差集+1比较. 这种枚举集合的思想还是第一次遇到,果然太弱了....~~~~ 其中枚举集合 for(s0=s;s0;s0=(s0-1)&s) #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> usin

uva 11795(状态压缩dp)

题意:有一个机器人要杀死其他n(1 <= n <= 16)个机器人,他自己配备了一个武器,并且给出了这个武器能杀死的敌人,如101表示他能杀死第1和第3个敌人,这样他就能得到第1和第3号敌人的武器,从而杀死更多的敌人,问他杀死所有的敌人的方法数. 题解:因为敌人数最多是16个,很容易想到应该是状态压缩dp,可以用f[S]表示状态S下进制位为1的敌人全被杀死的方案数,那么结果就是f[(1 << n) - 1],如果拿掉了状态S中的杀死第j个人能得到的武器,剩下的人如果能杀死第j个人,

poj 3311 Hie with the Pie (状态压缩+最短路)

Hie with the Pie Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 4491   Accepted: 2376 Description The Pizazz Pizzeria prides itself in delivering pizzas to its customers as fast as possible. Unfortunately, due to cutbacks, they can affo

uva 11195 Another queen (用状态压缩解决N后问题)

题目链接:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2136 Problem A Another n-Queen Problem I guess the n-queen problem is known by every person who has studied backtracking. In this problem you s

UVa 1252 - Twenty Questions(记忆化搜索,状态压缩dp)

题目链接:uva 1252 题意: 有n个长度为m的二进制串,每个都是不同的. 为了把所有字符串区分开,你可以询问,每次可以问某位上是0还是1. 问最少提问次数,可以把所有字符串区分开来. 思路来源于:点击打开链接 思路: m很小,可以考虑状态压缩. dp[s1][s2]表示询问的状态为s1时,此时能猜到状态包含s2时最小需要的步数. 当询问的几位=s2的二进制串小于2时就能区分出来了,dp[s1][s2]=0: 不能区分则再询问一次,s1|=(1<<k),如果问某位为0,则s2不变,问某位为

UVA 11825 - Hackers&amp;#39; Crackdown 状态压缩 dp 枚举子集

UVA 11825 - Hackers' Crackdown 状态压缩 dp 枚举子集 ACM 题目地址:11825 - Hackers' Crackdown 题意: 有一个由编号0~n-1的n台计算机组成的网络,一共同拥有n种服务,每台计算机上都执行着所有服务,对于每台计算机,你能够选择停止一项服务,这个行为会导致与这台计算机和与他相连的其它计算机上的这项服务都停止(原来已经停止的继续保持停止状态). 求最多能使多少个服务瘫痪(即没有不论什么一台计算机在执行这项服务). 分析: 题目说白了.就

uva 11367 dijkstra+dp状态压缩

题意:给出n个地点 和 每个地点的油价 ,有 m 条边 , 并给出每条边长度 .1单位汽油可以走1千米  , 油箱的容量为 c , 在初始点 s 时 , 油箱中的油为 0 , 求s 到 t 的最小花费 . 解法: 定义 状态 d[i][j] 表示到达 地点 i 且油箱中有 j 单位油时的最小 花费. 对于状态的转移时 , 有两种方法: 1.把每个点的所有状态都求出 2.不把每个点的状态都求出 , 而是一单位一单位的加油. 对于第一种方法 , 会超时 , 因为每个点的状态太多 , 但是能用的状态就