http://acm.hi-54.com/problem.php?pid=2113

题意:

给出总金钱数E,和每次搬运需要的金钱数F,(每次可以拿走体积为1 的小正方体,当然也可以将一个小正方体从i出移到j处  花费都是F)

然后给出矩阵行和列n,m  (e<10^12,n<100,m<100)

下面就是n*m个数,不同的数表示对应的高度。

求出在三视图保持不变以及不超过总钱数的前提下,所能拿出的小正方体的最大体积。(最完美翻译 ,请网上查找英文版本)

 

题解思路:根据矩阵,求出最优的三视图矩阵,然后比较得出最优解。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<queue>
#include<cmath>
using namespace std;
#define INF 0x3f3f3f3f
#define LL long long
#define N 103
LL e,f,n,m;
LL a[N][N],map[N][N],x[N],y[N],xx[N],yy[N];
void qingkong()
{
    memset(map,0,sizeof(map));
    memset(a,0,sizeof(a));
    memset(xx,0,sizeof(xx));
    memset(yy,0,sizeof(yy));
}
void zuidazhi()
{
    for(int i=1; i<=n; i++)
    {
        LL maxx=-1;
        for(int j=1; j<=m; j++)
            maxx=max(maxx,map[i][j]);
        x[i]=maxx;///各行的最大值
    }
    for(int i=1; i<=m; i++)
    {
        LL maxx=-1;
        for(int j=1; j<=n; j++)
            maxx=max(map[j][i],maxx);
        y[i]=maxx;///各列的最大值
    }
}
void gouzaozuiyou()
{///先将矩阵按照三视图构造成最优图
    for(int i=1; i<=n; i++)
        for(int j=1; j<=m; j++)
            if(x[i]==y[j]&&!yy[j]&&map[i][j])
            {///行列相同为最优值
                xx[i]=1;
                yy[j]=1;///表示行列最大值是否使用
                a[i][j]=x[i];
                break;
            }
    for(int i=1; i<=n; i++)
    {//将各行剩余的最大值  插入合适的列中
        if(xx[i]) continue;
        for(int j=1; j<=m; j++)
        {///即列最大值大于等于行最大值时
            if(y[j]>=x[i]&&map[i][j])
            {///不要忘记等于的情况
                a[i][j]=x[i];
                xx[i]=1;
                break;
            }
        }
    }
    for(int i=1; i<=m; i++)
    {///同上
        if(yy[i]) continue;
        for(int j=1; j<=n; j++)
        {
            if(x[j]>=y[i]&&map[j][i])
            {
                a[j][i]=y[i];
                yy[i]=1;
                break;
            }
        }
    }
    for(int i=1; i<=n; i++)
    {
        for(int j=1; j<=m; j++)
        {
            int c=0,d=0;
            for(int k=1; k<=n; k++)
                if(a[i][j]==a[k][j]&&i!=k) c=1;
            for(int k=1; k<=m; k++)
                if(a[i][j]==a[i][k]&&j!=k) d=1;
            if(c&&d&&a[i][j])
                a[i][j]=1;
        }
    }
}
void gouchengtu()///最终的最优构成图
{
    for(int i=1; i<=n; i++)
    {
        for(int j=1; j<=m; j++)
            printf("%lld ",a[i][j]);
        printf("\n");
    }
}
void shujucha()///数据差
{ ///根据题意  找出  数据查  求出最佳值
    LL ans=0,sum=0;
    for(int i=1; i<=n; i++)
    {
        for(int j=1; j<=m; j++)
        {
            if(map[i][j]>a[i][j])
                sum+=map[i][j];
            ans+=map[i][j]-a[i][j];
        }
    }
    if(sum>=e/f)
        printf("%lld\n",e/f);
    else printf("%lld\n",ans);
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        qingkong();
        scanf("%lld %lld %lld %lld",&e,&f,&n,&m);
        for(int i=1; i<=n; i++)
            for(int j=1; j<=m; j++)
                scanf("%lld",&map[i][j]);
        for(int i=1; i<=n; i++)
            for(int j=1; j<=m; j++)
                if(!a[i][j]&&map[i][j])
                    a[i][j]=1;
        zuidazhi();///求出各行各列的最大值
        gouzaozuiyou();///按照三视图  求出最优
        /// gouchengtu();  /// 给出矩阵的面积最小图
        shujucha();///根据题意  求出相应结果
    }
    return 0;
}

 

posted on 2018-06-05 17:51  云胡不喜。  阅读(940)  评论(0编辑  收藏  举报