zoukankan      html  css  js  c++  java
  • 【网络流 24 题】【Luogu P2761】 软件补丁问题

    题目大意:

    有一个长度为 (n) 的只包含 '-' 或 '+' 的字符串,刚开始全是 '+',还有 (m) 次操作,每次操作有一个时间 (c)、两个只包含 '-'、'+'、'0' 的 字符串(A) 和 字符串(B),如果字符串和 字符串(A) 相等(字符串(A) 中 '0' 的位置不算),那字符串就可以变为 字符串(B)(字符串(A) 中 '0' 的位置不算),每次操作要耗 (c)。问最少多少时间让字符串全变为 '-'。

    正文:

    因为 (nleq 20), 所以可以使用状态压缩,'-' 和 '+' 分别用 '0' 和 '1' 来表示。根据原题我们可以用位运算来判断原字符串是否与字符串 (A) 相等:

    if((u & b1[i]) == b1[i] && (u & b2[i]) == 0)
    

    b1[i]b2[i] 都是原文提到的。)

    还是根据原题可以将字符串变为 字符串(B)

    ((u | f1[i]) ^ f1[i]) | f2[i]
    

    f1[i]f2[i] 也都是原文提到的。)

    得到这些就可以用最短路解决本题了,我采用了 SPFA。

    代码:

    const int N = 110;
    
    int n, m; 
    int b1[N], b2[N], f1[N], f2[N], TiMe[N];
    int dis[1 << 21];
    
    inline void read(int &x) 
    {
        char ch = getchar();
        while(ch < '0' || ch > '9')
    		ch = getchar();
        x = ch - 48; ch = getchar();
        while(ch >= '0' && ch <= '9') 
    	{
            x = x * 10 + (ch - 48);
            ch=getchar();
        }
    }
    
    queue <int> que;
    bool vis[1 << 21];
    
    void SPFA()
    {
    	memset(dis, 0x7f, sizeof dis);
    	dis[(1 << n) - 1] = 0;
    	que.push((1 << n) - 1);
    	while (!que.empty())
    	{
    		int u = que.front();que.pop();
    		for (int i = 1; i <= m; i++)
    		{
    			if((u & b1[i]) == b1[i] && (u & b2[i]) == 0)
    			{
    				int v = ((u | f1[i]) ^ f1[i]) | f2[i];
    				if(dis[u] + TiMe[i] < dis[v])
    				{
    					dis[v] = dis[u] + TiMe[i];
    					if(!vis[v])
    					{
    						que.push(v);
    						vis[v] = 1;
    					}
    				}
    			}
    		}
    		vis[u] = 0;
    	}
    }
    
    int main()
    {
    //	freopen(".in", "r", stdin);
    //	freopen(".out", "w", stdout);
    	read(n), read(m);
    	for (int i = 1; i <= m; i++)
    	{
    		read(TiMe[i]);
    	    char ch = getchar();
    	    while(ch != '+' && ch != '-' && ch != '0')
    			ch = getchar();
    		for(int j = 1; j <= n; ++j)
    		{
    			if(ch == '+')
    				b1[i] += 1 << (j - 1);
    			if(ch == '-')
    				b2[i] += 1 << (j - 1);
    			ch = getchar();	
    		}
    	    while(ch != '+' && ch != '-' && ch != '0')
    			ch = getchar();
    		for(int j = 1; j <= n; ++j)
    		{
    			if(ch == '-')
    				f1[i] += 1 << (j - 1);
    			if(ch == '+')
    				f2[i] += 1 << (j - 1);
    			ch = getchar();	
    		}
    	}
    	SPFA();
    	if (dis[0] == dis[(1<<21)-1]) puts("0");
    	else printf("%d
    ", dis[0]); 
        return 0;
    }
    
    
  • 相关阅读:
    ssh scp命令详解
    python模块与包
    python参数Sample Code
    python 多线程简介
    python virtualenv环境安装(ubuntu)
    python pip 代理设置
    mysql资源总结
    mysql索引原理及用法
    Oracle学习笔记:利用user_segments查表的大小
    Oracle学习笔记:dba_tables、all_tables、user_tables区别
  • 原文地址:https://www.cnblogs.com/GJY-JURUO/p/12596048.html
Copyright © 2011-2022 走看看