编程之美2014格格取数

#include<iostream>

typedef struct
{
    int x,y,key,p;
} Max;

void QuickSortRowP(Max R[100][100],int x,int s, int t)
{
    int i=s, j=t;
    Max tmp, tra;
    if(s<t)
    {
        tmp=R[x][s];
        while(i!=j)
        {

            while(j>i&&R[x][j].p>=tmp.p)
            {
                j--;
            }
            tra=R[x][i];
            R[x][i]=R[x][j];
            R[x][j]=tra;
            while(i<j&&R[x][i].p<tmp.p)
            {
                i++;
            }
            tra=R[x][j];
            R[x][j]=R[x][i];
            R[x][i]=tra;
        }
        R[x][i]=tmp;
        QuickSortRowP(R,x,s,i-1);
        QuickSortRowP(R,x,i+1,t);
    }
}

void QuickSortCol(Max R[100][100],int y,int s, int t)
{
    int i=s, j=t;
    Max tmp, tra;
    if(s<t)
    {
        tmp=R[s][y];
        while(i!=j)
        {
            while(j>i&&R[j][y].key>=tmp.key)
            {
                j--;
            }
            tra=R[i][y];
            R[i][y]=R[j][y];
            R[j][y]=tra;
            while(i<j&&R[i][y].key<tmp.key)
            {
                i++;
            }
            tra=R[j][y];
            R[j][y]=R[i][y];
            R[i][y]=tra;
        }
        R[i][y]=tmp;
        QuickSortCol(R,y,s,i-1);
        QuickSortCol(R,y,i+1,t);
    }
}


int main()
{
    int T,m,n,t,i,j,ii,jj,coun,LACK,NEWLACK,flag,sum[100],OPER[100],RF[100][100];
    Max conum[100][100],CHOOSE[100],TEMP;
    std::cin>>T;
    for(t=0; t<T; ++t)
    {
        std::cin>>m>>n;
        for(i=0; i<m; ++i) //input
        {
            for(j=0; j<n; ++j)
            {
                std::cin>>conum[i][j].key;
                conum[i][j].p=0;
                conum[i][j].x=i;
                conum[i][j].y=j;
            }
        }
        if(m>n)
        {
            for(j=0; j<n; ++j) //reverse
            {
                for(i=j+1; i<m; ++i)
                {
                    conum[j][i].p=0;
                    ii=conum[j][i].y;
                    conum[j][i].y=conum[i][j].x;
                    conum[i][j].x=ii;
                    ii=conum[j][i].x;
                    conum[j][i].x=conum[i][j].y;
                    conum[i][j].y=ii;
                    ii=conum[j][i].key;
                    conum[j][i].key=conum[i][j].key;
                    conum[i][j].key=ii;
                }
            }
            i=m;
            m=n;
            n=i;
        }
        for(j=0; j<n; ++j)//col sort <- key step
        {
            QuickSortCol(conum,j,0,m-1);
        }
        for(j=0; j<n; ++j)//p increase initialize
        {
            for(i=0; i<m; ++i)
            {
                conum[i][j].p=conum[i][j].key-conum[0][j].key;
            }
        }
        for(j=0; j<n; ++j)//CHOOSE and OPER initialize
        {
            CHOOSE[j]=conum[0][j];
            OPER[j]=0;
        }

        coun=0;
        for(j=0; j<n; ++j) //LACK initialize
        {
            for(i=0; i<m; ++i)
            {
                if(CHOOSE[j].x==i)
                {
                    OPER[i]+=1;
                }
            }
        }
        for(i=0; i<m; ++i)
        {
            if(OPER[i])
            {
                coun+=1;
                OPER[i]=0;
            }
        }
        LACK=m-coun;
        coun=0;
        for(i=0; i<m; ++i)
        {
            QuickSortRowP(conum,i,0,n-1);
        }
        for(i=0; i<m; ++i)//RF initialize
        {
            for(j=0; j<n; ++j)
            {
                RF[i][j]=1;
            }
        }
        for(j=0; j<n; ++j)
        {
            RF[0][j]=0;
        }
        while(LACK)
        {
            for(j=0; j<n; ++j)
            {
                for(i=0; i<m; ++i)
                {
                    if(RF[i][j]==1)
                    {
                        TEMP=CHOOSE[conum[i][j].y];//TEMP initialize
                        CHOOSE[conum[i][j].y]=conum[i][j];
                        flag=conum[i][j].y;//flag initialize
                        //compute new lack
                        for(jj=0; jj<n; ++jj)
                        {
                            for(ii=0; ii<m; ++ii)
                            {
                                if(CHOOSE[jj].x==ii)
                                {
                                    OPER[ii]+=1;
                                }
                            }
                        }
                        for(ii=0; ii<m; ++ii)
                        {
                            if(OPER[ii])
                            {
                                coun+=1;
                                OPER[ii]=0;
                            }
                        }
                        NEWLACK=m-coun;//NEWLACK initialize
                        coun=0;
                        //
                        if(NEWLACK<LACK)
                        {
                            LACK=NEWLACK;
                            RF[i][j]=0;
                            continue;
                        }
                        else
                        {
                            CHOOSE[flag]=TEMP;
                        }
                    }
                }
            }
        }
        sum[t]=0;//sum initialize
        for(j=0; j<n; ++j)
        {
            sum[t]+=CHOOSE[j].key;
        }
    }//T!! do not delete
    for(t=0; t<T; ++t)
    {
        std::cout<<"Case "<<t+1<<": "<<sum[t]<<std::endl;
    }
}//main!! do not delete


矩阵采用结构体,记录所在的x轴、y轴位置,key值和一个辅助变量p,p记录垂直排序后每一列的递增情况。


 变量说明:


 T,m,n//循环次数,行,列   ,t,i,j,ii,jj// 计数    coun,LACK,NEWLACK,OPER[100]//用于计算未覆盖的行数     flag//标记     RF[100][100]//辅助矩阵     sum[100]//记录结果 conum[100][100]//结构矩阵      CHOOSE[100]//选出的元素 


没有刻意遵循某种算法,总体上是按照排序优先的原则进行遍历,个人认为行和列中较大的值代表必须选出的元素的总数。


 大致思想是先考虑每一列再考虑每一行。首先使列数n恒大于等于行数m(不满足则转置),对每一列垂直排序,最上方一行即为每一列最小值的组合并作为CHOOSE[]的初始值。如果CHOOSE[]没有覆盖每一行,对除第一行外,对列的递增情况进行水平排序;计算未覆盖行数LACK,判断是否覆盖了每一行,如果没有覆盖全部行则循环更新CHOOSE[]和LACK直到完全覆盖每一行为止。


自己测试多组数据都是对的,不知道为什么WA,就当写着玩儿了~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值