• UVA 1104 【芯片难题 Chips Challenge】


    Description

    传送门


    Solution

    因为每一行最多方的芯片数量是随着芯片总数量变化的,这样不好整,所以我们枚举最大数量,用网络流跑出此时最多放置多少芯片如果比我们枚举的最大数量是合法的,就更新答案。

    建立(a_i)表示行,建立(b_i)表示列。

    (S)(a_i)连容量为该行可放置芯片数量和已经放好的芯片数量的和,费用为(0)的有向边。

    (b_i)(T)连容量为该行可放置芯片数量和已经放好的芯片数量的和,费用为(0)的有向边,

    (a_i)(b_i)连容量为枚举的最大数量,费用为(0)的有向边,如果流过这条边代表放置芯片。

    如果一个位置((i, j))可以放置芯片,那么从(a_i)(b_j)连容量为(1),费用为(1)的有向边,如果流过这条边表示这个位置不放置芯片。

    这样建模之后跑最小费用最大流,最大流限制了对每个位置都会进行放和不放的决策,最小费用保证了求出的方案不放的数量最少即放的芯片数量最多。


    Code

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <queue>
    using namespace std;
    
    const int INF = 999999999;
    const int N = 1000050;
    const int M = 2000050;
    
    int n, s, t, head[N], cur[N], d[N], vis[N], num = 1, cnt, y[N], ans, maxflow, mincost, a, b, maxt, sum, hav, cd[5050], rd[5050];
    
    char st[5050][5050];
    
    struct Node
    {
    	int next, to, flow, dis;
    } edge[M * 2];
    
    void Addedge(int u, int v, int w, int c)
    {
    	edge[++num] = (Node){ head[u], v, w, c};
    	head[u] = num;
    }
    
    void Add(int u, int v, int w, int c)
    {
    	Addedge(u, v, w, c);
    	Addedge(v, u, 0, -c);
    	return; 
    }
    
    template <class T>
    void Read(T &x)
    {
    	x = 0; int p = 0; char st = getchar();
    	while (st < '0' || st > '9') p = (st == '-'), st = getchar();
    	while (st >= '0' && st <= '9') x = (x << 1) + (x << 3) + st - '0', st = getchar();
     	x = p ? -x : x;
     	return;
    }
    
    template <class T>
    void Put(T x)
    {
    	if (x < 0) putchar('-'), x = -x;
    	if (x > 9) Put(x / 10);
    	putchar(x % 10 + '0');
    	return; 
    }
    
    int Bfs()
    {
    	queue<int> q;
    	for (int i = 0; i <= t; i++) d[i] = INF, vis[i] = 0;
    	d[s] = 0; vis[s] = 1; q.push(s);
    	while (!q.empty())
    	{
    		int u = q.front(); q.pop(); vis[u] = 0;
    		for (int i = head[u]; i; i = edge[i].next)
    			if (edge[i].flow > 0 && d[edge[i].to] > d[u] + edge[i].dis)
    			{
    				d[edge[i].to] = d[u] + edge[i].dis;
    				if (!vis[edge[i].to])
    				{
    					vis[edge[i].to] = 1;
    					q.push(edge[i].to);
    				}
    			}	
    	} 
    	return d[t] != INF;
    }
    
    int Dinic(int x, int flow)
    {
    	if (x == t || !flow) return flow;
    	int rest = flow, k;
    	vis[x] = 1;
    	for (int i = cur[x]; i && rest; i = edge[i].next)
    	{
    		int v = edge[i].to;
    		cur[x] = i;
    		if (!vis[edge[i].to] && edge[i].flow > 0 && d[edge[i].to] == d[x] + edge[i].dis)
    		{
    			int v = edge[i].to;
    			int k = Dinic(v, min(rest, edge[i].flow));
    		//	if (!k) dis[edge[i].to] = INF;
    			rest -= k;
    			edge[i].flow -= k;
    			edge[i ^ 1].flow += k;
    			mincost += k * edge[i].dis;
    		}
    	}
    	vis[x] = 0;
    	return flow - rest;
    }
    
    void Solve()
    {
    	while(Bfs())
    	{
    		for (int i = 0; i <= t; i++) cur[i] = head[i]; 
    		maxflow += Dinic(s, INF);
    	}
    	return; 
    }
    
    int main()
    {
    	int tmp = 0;
        while (scanf("%d%d%d", &n, &a, &b) == 3)
        {
    		if (!n) return 0;
    		printf("Case %d: ", ++tmp);
    		s = 0; t = n * 2 + 1;
    		sum = 0; ans = -1; hav = 0;
    		memset(rd, 0, sizeof (rd));
    		memset(cd, 0, sizeof (cd));
    		for (int i = 1; i <= n; i++)
    		{
    			scanf("%s", st[i] + 1);
    			for (int j = 1; j <= n; j++)
    			{
    				if (st[i][j] == 'C' || st[i][j] == '.')
    				{
    					sum++; cd[i]++; rd[j]++;
    					if (st[i][j] == 'C') hav++;
    				}
    			}
    		}
    		for (int maxt = 0; maxt <= n; maxt++)
    		{
    			num = 1; memset(head, 0, sizeof(head));
    			for (int i = 1; i <= n; i++)
    			{
    				Add(s, i, cd[i], 0);
    				Add(i, i + n, maxt, 0);
    				Add(i + n, t, rd[i], 0);
    				for (int  j = 1; j <= n; j++)
    					if (st[i][j] == '.') Add(i, j + n, 1, 1);
    			}
    			maxflow = mincost = 0;
    			Solve();
    			if (maxflow == sum && (maxflow - mincost) * a >= maxt * b) ans = max(ans, maxflow - mincost);
    		}
    		if (~ans) printf("%d
    ", ans - hav);
    		else puts("impossible");
        }
    	return 0;
    }
    
  • 相关阅读:
    mobx源码解读1
    表单元素之图形系
    koa2+koa-views示例
    avalon2的后端渲染实践
    向一个数组中插入元素
    一步步编写avalon组件02:分页组件
    avalon2学习教程15指令总结
    avalon2学习教程14动画使用
    WPF动态加载Menu菜单
    WPF自定义控件与样式 ---- 系列文章
  • 原文地址:https://www.cnblogs.com/Tian-Xing-Sakura/p/13097851.html
Copyright © 2020-2023  润新知