HDU 5556

题意:  有一个农场大小为n*m  里面有一些古老的农田,你现在需要新建一些农田,要求新建的农田之间不能相连,古老的农田不可拆分,如果你选择了一块土地(原为古老的农田)建立新农田则需要把该块古老的农田全部包含。

解法: 如果没有古老的农田只要对所有空地和它相邻的空地建边,然后求一遍最大独立集即可。     所以我们需要移除古老的农田的影响,因为古老的农田最多只有10块,所以我们只需要枚举选择了哪些古老的农田建立新的农田,然后移除与这些古老农田相邻的空地,然后求一遍最大独立集,然后取所求值得最大值即可得到答案。
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<stack>
#include<queue>
#include<algorithm>
#include<vector>
using namespace std;
int y[105];
bool vis[105];
vector<int> G[105];
bool visx[105];
bool visy[105];
bool dfs(int v)
{
    //cout<<v<<endl;
    for(int i=0;i<G[v].size();i++)
    {
        int e=G[v][i];
        if(vis[e]||visy[e]) continue;
        vis[e]=1;
        if(y[e]==-1||dfs(y[e]))
        {
            y[e]=v;
            return true;
        }
    }
    return false;
}
int maxx;
int maxy;
int xyl()
{
    int cnt=0;
    memset(y,-1,sizeof(y));
    for(int i=0;i<maxx;i++)
    {
        memset(vis,0,sizeof(vis));
        //cout<<i<<endl;
        if(!visx[i]&&dfs(i))
            cnt++;
        //cout<<i<<endl;
    }
    return cnt;
}
char s[15][15];
bool vis1[15];
int bh[15][15];
int dx[4]={1,0,-1,0};
int dy[4]={0,1,0,-1};
int n,m;
bool temp[15];
int res;
bool flag[15][15];
void solve(int p,int _k)
{
    //cout<<p<<endl;
    if(p==10)
    {
        memset(visx,0,sizeof(visx));
        memset(visy,0,sizeof(visy));
        int cnt=0;
        int cnt1=0;
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<m;j++)
            {
                if(s[i][j]=='.')
                for(int k=0;k<4;k++)
                {
                    int nx=i+dx[k];
                    int ny=j+dy[k];
                    if(nx>=0&&ny>=0&&nx<n&&ny<m&&s[nx][ny]!='.')
                    {
                        int __k=s[nx][ny]-'0';
                        if(temp[__k])
                        {
                            if(i%2==j%2)
                            {
                                cnt++;
                                visx[bh[i][j]]=1;
                            }
                            else
                            {
                                cnt1++;
                                visy[bh[i][j]]=1;
                            }
                            break;
                        }
                    }
                }
            }
        }
        //cout<<maxx<<endl;
        int rr=xyl();
        //cout<<rr<<" "<<maxx<<" "<<maxy<<" "<<cnt<<" "<<cnt1<<" "<<_k<<endl;
        rr=maxx+maxy-cnt-rr-cnt1;
        //cout<<rr<<" "<<cnt<<" "<<_k<<" "<<maxx<<endl;
        res=max(res,rr+_k);
    }
    else
    {
        if(!vis1[p]) solve(p+1,_k);
        else
        {
            solve(p+1,_k);
            bool he=0;
            for(int i=0;i<p;i++)
            {
                //cout<<i<<" "<<temp[i]<<" "<<" "<<flag[i][p]<<endl;
                if(temp[i]&&flag[i][p])
                {
                    he=1;
                    break;
                }
            }

            if(!he)
            {
                temp[p]=1;
                solve(p+1,_k+1);
                temp[p]=0;
            }
        }
    }
}
int main()
{
    int t;
    scanf("%d",&t);
    int ca=0;
    while(t--)
    {
        //int n,m;
        scanf("%d%d",&n,&m);
        for(int i=0;i<n*m;i++) G[i].clear();
        for(int i=0;i<n;i++) scanf("%s",s[i]);
        memset(vis,0,sizeof(vis));
        int X=0,Y=0;
        memset(flag,0,sizeof(flag));
        memset(vis1,0,sizeof(vis1));
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<m;j++)
            {
                if(s[i][j]!='.')
                {
                    int _k=s[i][j]-'0';
                    vis1[_k]=1;
                    for(int k=0;k<4;k++)
                    {
                        int nx=i+dx[k];
                        int ny=j+dy[k];
                        if(nx>=0&&ny>=0&&nx<n&&ny<m&&s[nx][ny]!='.')
                        {
                            //cout<<_k<<" "<<s[nx][ny]<<endl;
                            flag[_k][s[nx][ny]-'0']=flag[s[nx][ny]-'0'][_k]=1;
                        }
                    }
                }
                else
                {
                    if(i%2==j%2)
                    {
                        bh[i][j]=X++;
                    }
                    else bh[i][j]=Y++;
                    //cout<<i<<" "<<j<<" "<<bh[i][j]<<endl;
                }
            }
        }
        //cout<<"~~~~~"<<endl;
        for(int i=0;i<n;i++)
        {
            for(int j=i%2;j<m;j+=2)
            {
                if(s[i][j]=='.')
                {
                    for(int k=0;k<4;k++)
                    {
                        int nx=i+dx[k];
                        int ny=j+dy[k];
                        if(nx>=0&&ny>=0&&nx<n&&ny<m&&s[nx][ny]=='.')
                        {
                            //cout<<bh[i][j]<<" "<<bh[nx][ny]<<"~~~"<<endl;
                            G[bh[i][j]].push_back(bh[nx][ny]);
                        }
                    }
                }
            }
        }
        maxx=X;
        maxy=Y;
        memset(temp,0,sizeof(temp));
        res=0;
        //cout<<"~~~"<<endl;
        solve(0,0);
        printf("Case #%d: %d\n",++ca,res);
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值