再谈组合模式

http://acm.hdu.edu.cn/showproblem.php?pid=1507

大致题意:在一个n*m的格子上,黑色的地方不可用,问在白色格子上最多可放多少1*2的矩阵。

思路:建图,每个白色格子与它临近的上下左右的白色格子建边,求最大匹配,答案为最大匹配/2,因为是双向图。最后输出匹配边时,当找到一组匹配边记得将该边标记,以防重复计算。

#include <stdio.h>
#include <algorithm>
#include <set>
#include <map>
#include <vector>
#include <math.h>
#include <string.h>
#include <queue>
#define LL long long
#define _LL __int64
using namespace std;
const int INF = 0x3f3f3f3f;
const int mod = 1000000007;
const int maxn = 110;

int n,m,k;
vector <int> edge[maxn];
int Map[maxn][maxn];
int match[10010],chk[10010];
int cnt;

int addre[10010];
void debug()
{
	for(int i = 1; i <= n; i++)
	{
		for(int j = 1; j <= m; j++)
			printf("%d%d ",Map[i][j],addre[Map[i][j]]);
		printf("\n");
	}
}
int dfs(int p)
{
    for(int i = 0; i < (int)edge[p].size(); i++)
    {
        int q = edge[p][i];
        if(!chk[q])
        {
            chk[q] = 1;
            if(match[q] == -1 || dfs(match[q]))
            {
                match[q] = p;
                return 1;
            }
        }
    }
    return 0;
}

void output()
{
	int vis[10010];
	int x,y,xx,yy,tmp;
	memset(vis,0,sizeof(vis));

	for(int i = 1; i <= cnt; i++)
	{
		if(match[i] != -1 && !vis[i])
		{
			tmp = match[i];
			if(!vis[tmp] && i != tmp)
			{
				vis[i] = 1;
				vis[tmp] = 1;
				xx = addre[tmp]/m+1;
				yy = addre[tmp]%m+1;
				x = addre[i]/m+1;
				y = addre[i]%m+1;
				printf("(%d,%d)--(%d,%d)\n",x,y,xx,yy);
			}
		}
	}
}

int main()
{
    int u,v;
    while(~scanf("%d %d",&n,&m) && (n || m))
    {
        for(int i = 1; i <= n*m; i++)
            edge[i].clear();
        memset(Map,-1,sizeof(Map));
        scanf("%d",&k);

        for(int i = 0; i < k; i++)
        {
            scanf("%d %d",&u,&v);
            Map[u][v] = 0;
        }

        cnt = 0;
        int tmp = -1;
        for(int i = 1; i <= n; i++)
        {
            for(int j = 1; j <= m; j++)
            {
            	tmp++;
                if(Map[i][j] < 0)
                {
                    cnt++;
                    addre[cnt] = tmp;
                    Map[i][j] = cnt;
                }
            }
        }
        //debug();

        for(int i = 1; i <= n; i++)
        {
            for(int j = 1; j <= m; j++)
            {
                if(Map[i][j] == 0) continue;
                if(i-1 >= 1 && Map[i-1][j]>0)
                    edge[Map[i][j]].push_back(Map[i-1][j]);
                if(i+1 <= n && Map[i+1][j]>0)
                    edge[Map[i][j]].push_back(Map[i+1][j]);
                if(j-1 >= 1 && Map[i][j-1]>0)
                    edge[Map[i][j]].push_back(Map[i][j-1]);
                if(j+1 <= m && Map[i][j+1]>0)
                    edge[Map[i][j]].push_back(Map[i][j+1]);
            }
        }

        memset(match,-1,sizeof(match));
        int ans = 0;
        for(int i = 1; i <= cnt; i++)
        {
            memset(chk,0,sizeof(chk));
            ans += dfs(i);
        }
        printf("%d\n",ans/2);
		output();
    }

    return 0;
}

再谈组合模式

时间: 2024-07-31 07:59:34

再谈组合模式的相关文章

使用JavaScript浅谈组合模式

什么是组合模式? 从前有座山,山上住着一个老和尚和小和尚,老和尚给小和尚讲了一个故事,这个故事是这样子的:从前有座山,山上住着一个老和尚和小和尚,老和尚给小和尚讲了一个故事,这个故事是这样子的:从前有座山,山上住着一个老和尚和小和尚,老和尚给小和尚讲了一个故事,这个故事是这样子的... 骚年,读到这里不知道你明白了什么,一个故事由另一个故事组成,然后一直这样子组合下去,形成了一个最大的故事. 没错,这就是组合模式:小对象组合成一个大对象,小对象可能由更小的对象组合而成. 其实我们也可以看出两点:

浅谈组合模式、桥接模式

组合模式:是一种树形结构 桥接模式:N个操作系统,M个不同品牌电脑 电脑虚基类:实现install_os(os*) 操作系统虚基类:实现install() linux = new LinuxOS() windows = new WindosOS() pc = new ApplePC() pc->install_os(linux) pc->install_os(windows ) 个人理解:两个相关但独立的类,通过接口(虚函数)的方式通过函数调用关联起来. 原文地址:https://www.cn

再谈pipeline-filter模式

本文结合最近我正在实现的一个基于RabbitMQ的消息总线上所走的弯路来谈谈设计层面上的责任链模式以及架构层面上的pipeline-filter模式.写这篇文章的另一个目的是为了纠正我之前针对pipeline-filter模式写的一篇博文:<pipeline-filter模式变体之尾循环>,如果你想看看我之前为什么要那么做,你可以先看看那篇文章,不过无论看不看都不影响这篇文章的行文. 消息总线需要扩展性 目前这个消息总线实现了produce/consume.request/response.p

站在新语言平台上再谈&quot;组合&quot;与&quot;继承&quot;

长久以来,OO编程思想的一个重要信条是:多用组合,少用继承,这被广为接受和认可.Scala引入Trait(特质)之后,这一点"似乎"受到了冲击,你可以看到,在很多Scala代码里出现了通过继承多个Trait为一个Class混入(追加)新功能的案例,而其中有不少案例是过去我们在传统OO语言(例如Java)中不会或不建议的做法,因为看上去那确实是在滥用继承. 举个简单的例子,日志功能是非常普遍的需求,传统的Java程序里是以"组合"的方式为一个类添加这一功能的,也就是在

再谈组合

#include <iostream> int num[20]; using namespace std; int sum = 0; void init(int nn, int mm) { int i; if (mm == 0)//当mm==0时,num[1]~num[5]中存储的就是枚举的这五个数 { sum++; for (int i = 1; i <= 5; i++) cout << num[i] << " "; cout <<

GoF设计模式三作者15年后再谈模式

Erich Gamma, Richard Helm, 和 Ralph Johnson在GoF设计模式发表15年以后,再谈模式,另外一位作者,也是四色原型的发明者Peter已经过世. 提问者:如今有85,000 iPhone的小应用遍布全球,使用PHP就能够写一个简单的"Hello, World! The time is X"Web网页,那么,面向对象设计是难的,这句话是否还正确呢? Richard Helm: 软件设计总是很难的,尽管大多数现代开发环境已经降低了复杂性,通过重用库和工具

js架构设计模式——你对MVC、MVP、MVVM 三种组合模式分别有什么样的理解?

你对MVC.MVP.MVVM 三种组合模式分别有什么样的理解? MVC(Model-View-Controller)MVP(Model-View-Presenter)MVVM(Model-View-ViewModel)请大家谈一谈各自的理解吧,对比之下更能明确特征和适用的范围,菜鸟们畅所欲言,老鸟大牛们请多多指点! 2 条评论 按投票排序 按时间排序 10 个回答 王韦恩卑鄙,我编程序,我约. 知乎用户.里德.jogen 等人赞同 只是一点浅见啊 折叠也活该... M-V- X 本质都是一样的

C#设计模式之九组合模式(Composite Pattern)【结构型】

原文:C#设计模式之九组合模式(Composite Pattern)[结构型] 一.引言 今天我们要讲[结构型]设计模式的第四个模式,该模式是[组合模式],英文名称是:Composite Pattern.当我们谈到这个模式的时候,有一个物件和这个模式很像,也符合这个模式要表达的意思,那就是"俄罗斯套娃"."俄罗斯套娃"就是大的瓷器娃娃里面装着一个小的瓷器娃娃,小的瓷器娃娃里面再装着更小的瓷器娃娃,直到最后一个不能再装更小的瓷器娃娃的那个瓷器娃娃为止(有点绕,下面我会

[js高手之路]设计模式系列课程-组合模式+寄生组合继承实战新闻列表

所谓组合模式,就是把一堆结构分解出来,组成在一起,现实中很多这样的例子,如: 1.肯德基套餐就是一种组合模式, 比如鸡腿堡套餐,一般是是由一个鸡腿堡,一包薯条,一杯可乐等组成的 2.组装的台式机同理,由主板,电源,内存条,显卡, 机箱,显示器,外设等组成的 把一个成型的产品组成部件,分成一个个独立的部件,这种方式可以做出很多灵活的产品,这就是组合模式的优势 比如:家用台式机电脑,要求配置比较低, 这个时候只需要主板+电源+内存条+机箱+显示器+外设就可以了,不需要配置独立显卡 鸡腿堡+鸡翅+紫薯