zoukankan      html  css  js  c++  java
  • UVA11419 SAM I AM 我是 SAM

    题面


    题面:给出一个(R imes C)大小的网格,网格上面放了一些目标。可以在网格外发射子弹,子弹会沿着垂直或者水平方向飞行,并且打掉飞行路径上的所有目标,如图所示。你的任务是计算出最少需要多少子弹,各从哪些位置发射,才能把所有目标全部打掉。


    感觉这就是典型的算法模板题,第一次可能想不出来,第二次就会了。


    建立一个二分图:左部点代表每一行,右部点代表每一列。如果一个目标在第(i)行第(j)列,就连一条(i o j)的边。
    那么我们的目标是选择最少的点,使每一条边至少有一个端点被选中,即二分图的最小点覆盖。根据König定理,最小点覆盖数=最大匹配数,所以直接跑匈牙利算法即可。
    但关于输出方案我还没有看懂,待以后补上。


    这里给两篇参考题解:
    https://www.cnblogs.com/colazcy/p/11515004.html
    https://blog.csdn.net/z309241990/article/details/34417693

    #include<cstdio>
    #include<iostream>
    #include<cmath>
    #include<algorithm>
    #include<cstring>
    #include<cstdlib>
    #include<cctype>
    #include<vector>
    #include<queue>
    #include<assert.h>
    #include<ctime>
    using namespace std;
    #define enter puts("") 
    #define space putchar(' ')
    #define Mem(a, x) memset(a, x, sizeof(a))
    #define In inline
    #define forE(i, x, y) for(int i = head[x], y; ~i && (y = e[i].to); i = e[i].nxt)
    typedef long long ll;
    typedef double db;
    const int INF = 0x3f3f3f3f;
    const db eps = 1e-8;
    const int maxn = 1e3 + 5;
    const int maxe = 1e6 + 5;
    In ll read()
    {
    	ll ans = 0;
    	char ch = getchar(), las = ' ';
    	while(!isdigit(ch)) las = ch, ch = getchar();
    	while(isdigit(ch)) ans = (ans << 1) + (ans << 3) + ch - '0', ch = getchar();
    	if(las == '-') ans = -ans;
    	return ans;
    }
    In void write(ll x)
    {
    	if(x < 0) x = -x, putchar('-');
    	if(x >= 10) write(x / 10);
    	putchar(x % 10 + '0');
    }
    In void MYFILE()
    {
    #ifndef mrclr
    	freopen("ha.in", "r", stdin);
    	freopen("ha.out", "w", stdout);
    #endif
    }
    
    int n, m, K;
    struct Edge
    {
    	int nxt, to;
    }e[maxe];
    int head[maxn], ecnt = -1;
    In void addEdge(int x, int y)
    {
    	e[++ecnt] = (Edge){head[x], y};
    	head[x] = ecnt;
    }
    
    bool vx[maxn], vy[maxn];
    int lft[maxn], rgt[maxn];
    In bool dfs(int now)
    {
    	vx[now] = 1;
    	forE(i, now, v) if(!vy[v])
    	{
    		vy[v] = 1;
    		if(!lft[v] || dfs(lft[v])) {lft[v] = now; rgt[now] = v; return 1;}
    	}
    	return 0;
    }
    In int hung()
    {
    	int ret = 0; Mem(lft, 0), Mem(rgt, 0);
    	for(int i = 1; i <= n; ++i)
    	{
    		Mem(vx, 0), Mem(vy, 0);
    		if(dfs(i)) ++ret;
    	}
    	return ret;
    }
    In void Find(int ans)
    {
    	Mem(vx, 0), Mem(vy, 0); 
    	for(int i = 1; i <= n; ++i) if(!rgt[i]) dfs(i);
    	write(ans);
    	for(int i = 1; i <= n; ++i) if(!vx[i]) space, putchar('r'), write(i);
    	for(int i = 1; i <= m; ++i) if(vy[i]) space, putchar('c'), write(i);
    	enter;
    }
    
    int main()
    {
    //	MYFILE();
    	while(scanf("%d%d%d", &n, &m, &K) && (n | m | K))
    	{
    		Mem(head, -1), ecnt = -1;
    		for(int i = 1; i <= K; ++i) 
    		{
    			int x = read(), y = read();
    			addEdge(x, y);
    		}
    		Find(hung());		
    	}
    	return 0;
    }
    
  • 相关阅读:
    移动端前台项目访问后台项目的基础路径写法【我】
    使用log4j将日志输送到控制台、文件或数据库中
    一、搭建简单的axis web服务
    o2s【我】
    新检出普通web项目爬坑记【我】
    Eclipse | 如何修改web项目的访问链接名,项目名
    unity3d 安卓IOS推送
    获取项目
    Unity3D性能优化--- 收集整理的一堆
    unity3d教程游戏包含的一切文件导入资源
  • 原文地址:https://www.cnblogs.com/mrclr/p/14775786.html
Copyright © 2011-2022 走看看