您的位置:首页 > 其它

hdu 5031 Lines

2014-11-19 16:38 267 查看
DFS暴力剪枝
2014广州网络赛的J题,

太恶心了,大模拟,狂搜索

Orz...............

注意最优化剪枝。

对于一个点,搜索时(此点必定是直线的起点,否则会数重的),先判断水平和竖直能不能划线(注意不要数重,当i==1 || j==1时才能竖直水平化);在枚举在此点下面的点,合法性剪枝,点数要大于3.

狠黄狠暴力。

输入输出优化 + G++交的,982ms

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#define inf 1000000000
using namespace std;
typedef long long ll;
void in(int &x){
    char ch; int minus = 0;
    while (ch=getchar(), (ch<'0'||ch>'9') && ch!='-');
    if (ch == '-') minus = 1, x = 0;
    else x = ch-'0';
    while (ch=getchar(), ch>='0'&&ch<='9') x = x*10+ch-'0';
    if (minus) x = -x;
}
void in(ll &x){
    char ch; int minus = 0;
    while (ch=getchar(), (ch<'0'||ch>'9') && ch!='-');
    if (ch == '-') minus = 1, x = 0;
    else x = ch-'0';
    while (ch=getchar(), ch>='0'&&ch<='9') x = x*10+ch-'0';
    if (minus) x = -x;
}
void out(int x){
    char hc[30];int len, minus=0;
    if (x<0) minus = 1, x = -x;
    len = 0; hc[len++] = x%10+'0';
    while (x/=10) hc[len++] = x%10+'0';
    if (minus) putchar('-');
    for (int i=len-1; i>=0; i--) putchar(hc[i]);
}
void out(ll x){
    char hc[30];int len, minus=0;
    if (x<0) minus = 1, x = -x;
    len = 0; hc[len++] = x%10+'0';
    while (x/=10) hc[len++] = x%10+'0';
    if (minus) putchar('-');
    for (int i=len-1; i>=0; i--) putchar(hc[i]);
}
const int N = 50+10;
int a

;
int n,m;
int sum;
int ans;
int isin(int x,int y)
{
    if(x>=1 && x<=n && y>=1 && y<=m) return 1;
    return 0;
}
void dfs(int now,int re)
{
    if(now>=ans) return ;
    if(re==0)
    {
        //printf("geng xi %d\n",now);
        ans = min(ans,now);
        return ;
    }
    int cnt = 0;
    for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) cnt = max(cnt,a[i][j]);
    if(now + cnt >=ans) return ;
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            if(a[i][j])
            {
                int fl=1,fll=1;
                if(i==1){
                    for(int k=1;k<=n;k++) if(!a[k][j]) {fl=0;break;}
                    if(fl)
                    {
                        for(int k=1;k<=n;k++) a[k][j]--;
                        dfs(now+1,re-n);
                        for(int k=1;k<=n;k++) a[k][j]++;
                    }
                }
                if(j==1){
                    for(int k=1;k<=m;k++) if(!a[i][k]) {fll=0;break;}
                    if(fll)
                    {
                        for(int k=1;k<=m;k++) a[i][k]--;
                        dfs(now+1,re-m);
                        for(int k=1;k<=m;k++) a[i][k]++;
                    }
                }

                for(int ii=i+1;ii<=n;ii++)
                {
                    for(int jj=1;jj<=m;jj++)
                    {
                        if(!a[i][j]) break;
                        if(!a[ii][jj]) continue;
                        if(ii==i || jj==j) continue;
                        int dx = ii-i,dy=jj-j;
                        int tx=i,ty=j;
                        int cn=0,flag=1;
                        while(1)
                        {
                            if(!isin(tx,ty)) break;
                            if(!a[tx][ty]) {flag=0;break;}
                            cn++;
                            tx+=dx;
                            ty+=dy;
                        }
                        tx=i-dx,ty=j-dy;
                        if(isin(tx,ty)) flag=0;
                        if(flag==0) continue;
                        if(cn<3) continue;
                        tx=i,ty=j;
                        while(1)
                        {
                            if(!isin(tx,ty)) break;
                            a[tx][ty]--;
                            tx+=dx;
                            ty+=dy;
                        }
                        //printf("直线 %d,%d --- %d,%d  cut = %d , now = %d ,re = %d\n",i,j,ii,jj,cn,now+1,re-cn);
                        dfs(now+1,re-cn);
                        tx=i,ty=j;
                        while(1)
                        {
                            if(!isin(tx,ty)) break;
                            a[tx][ty]++;
                            tx+=dx;
                            ty+=dy;
                        }
                    }
                }
                return ;
            }
        }
    }
}
int main()
{
    int t;
    in(t);
    while(t--)
    {
        sum=0;
        ans = inf;
        in(n);in(m);
        n++;m++;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
            {
                in(a[i][j]);
                sum+=a[i][j];
            }
        ans = min(14,sum/3);
        dfs(0,sum);
        out(ans);
        putchar('\n');
    }
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: