频道栏目
首页 > 资讯 > 其他 > 正文

Board Game- - 编程开发练习题

18-02-27        来源:[db:作者]  
收藏   我要投稿

Problem G. Board Game

Input: standard input

Output: standard output

Balloon Color: Orange

Feras bought to his nephew Saleem a new game to help him learning calculating. The game consists ofa board with 4 rows and 4 columns with 16 cubes. Every cube has a number from 1 to 16. Let’s definethe power of a column as the sum of its elements. In the same way, the power of a row is the sum of itselements. Saleem should arrange the cubes in the board such that the power of all columns and all rowsare equal. To make the game easier, the nice uncle, Feras, will help him arranging 7 cubes, and Saleemshould arrange the rest of the cubes.

Input

Your program will be tested on one or more test cases. The first line of the input will be a single integerT, the number of test cases (1 ≤ T ≤ 100). Then the test cases. Each test case has four lines containingfour integers. The j-th number in the i-th line describes the cell (i,j) of the board. If the number is -1 thenthe cell is empty and you have to fill it, otherwise, uncle Feras has already filled this cell.

Output

For each test case print a line in the following format: "Case c:"where c is the test case number startingfrom 1 then print the board in four lines every line has four numbers separated by space. If there is morethan one solution print the solution that has the smallest order (See the notes below).

Examples

standard input?

1

-1 -1 -1 -1

-1 -1 -1 -1

-1 5 13 12

3 8 9 14

standard output

Case 1:

11 6 10 7

16 15 2 1

4 5 13 12

3 8 9 14

Note

in the sample input there is more than one solution:

Solution1:

16 15 2 1

11 6 10 7

4 5 13 12

3 8 9 14

Solution2:

11 6 10 7

16 15 2 1

4 5 13 12

3 8 9 14

but we select solution2 because it has the smallest order when we write the rows in one line.

Solution1: 16 15 2 1 11 6 10 7 4 5 13 12 3 8 9 14

Solution2: 11 6 10 7 16 15 2 1 4 5 13 12 3 8 9 14

题意:

把1到16这些数放入一个4*4的矩形,使得每一行和每一列数加和都相等,已经放好7个数字,剩下9个数没放,求满足条件的矩形字典序最小的方案。

思路:

直接对每一个需要放的位置进行dfs,之后对其进行剪枝。

剪枝技巧:当某行或某列已填满数字,记录下其和,我们就可以在后面dfs时利用这个和进行填数的合法性进行校对,可省去不少时间。

代码有点乱且冗余。。。不过剪枝剪为15ms还是让我有点飘了O(∩_∩)O。

示例程序:

#include 
using namespace std;
int b[9],vis[9],flag,a[4][4],r[4],c[4],rmark[4],cmark[4];
void dfs(int deep,int buff,int num)
{
    int i,i1;
    if(flag==1)				//找到正解就不用找了
    {
        return;
    }
    if(deep==16)
    {
        for(i=0;4>i;i++)
        {
            for(i1=0;4>i1;i1++)
            {
                if(i1!=0)
                {
                    printf(" ");
                }
                printf("%d",a[i][i1]);
            }
            printf("\n");
        }
        flag=1;
        return;
    }
    if(a[deep/4][deep%4]!=-1)					//该位已填数直接到下一个
    {
        dfs(deep+1,buff,num);
        return;
    }
    for(i=0;9>i;i++)
    {
        if(vis[i]==0)
        {
            vis[i]=1;
            r[deep/4]=r[deep/4]+b[i];
            c[deep%4]=c[deep%4]+b[i];
            rmark[deep/4]=rmark[deep/4]+(1<<(deep%4));
            cmark[deep%4]=cmark[deep%4]+(1<<(deep/4));
            a[deep/4][deep%4]=b[i];				//以上进行填数后的状态更新
            if(cmark[deep%4]==15||rmark[deep/4]==15)			//填数后已把该行或列填满
            {
                if(buff==0)			//这是第一次填满,下面就利用和(num)去进行边填边校对
                {
                    if(rmark[deep/4]==15)				//行填满的情况
                    {
                        dfs(deep+1,1,r[deep/4]);
                    }
                    else if(cmark[deep%4]==15)			//列填满的情况
                    {
                        dfs(deep+1,1,c[deep%4]);
                    }
                }
                else				//不是第一次填满,就看看和(num)是否等于填满行或列的和
                {
                    if((r[deep/4]==num||rmark[deep/4]!=15)&&(c[deep%4]==num||cmark[deep%4]!=15))
                    {
                        dfs(deep+1,buff,num);
                    }
                }
            }
            else				//没有填满任何行列,继续dfs
            {
                dfs(deep+1,buff,num);
            }
            a[deep/4][deep%4]=-1;			//以下是回溯
            vis[i]=0;
            r[deep/4]=r[deep/4]-b[i];
            c[deep%4]=c[deep%4]-b[i];
            rmark[deep/4]=rmark[deep/4]-(1<<(deep%4));
            cmark[deep%4]=cmark[deep%4]-(1<<(deep/4));
        }
    }
}
int main()
{
    int t,i,i1,i2,buff,num,mark[17],top;
    scanf("%d",&t);
    for(i=1;t>=i;i++)
    {
        memset(r,0,sizeof(r));				//r数组记录每行数的和
        memset(c,0,sizeof(c));				//c数组记录每列数的和
        memset(mark,0,sizeof(mark));			//mark数组记录1到16有没有出现过
        memset(rmark,0,sizeof(rmark));			//rmark数组用二进制表示每行填数的情况
        memset(cmark,0,sizeof(cmark));			//cmark数组用二进制表示每列填数的情况
        buff=0;				//buff表示是否有一行或一列已填满数,dfs函数中的buff同理
        for(i1=0;4>i1;i1++)
        {
            for(i2=0;4>i2;i2++)
            {
                scanf("%d",&a[i1][i2]);
                if(a[i1][i2]!=-1)
                {
                    mark[a[i1][i2]]=1;
                    r[i1]=r[i1]+a[i1][i2];
                    c[i2]=c[i2]+a[i1][i2];
                    rmark[i1]=rmark[i1]+(1<=i1;i1++)
        {
            if(mark[i1]==0)
            {
                b[top++]=i1;				//取出需要填放的数
            }
        }
        flag=0;
        memset(vis,0,sizeof(vis));
        printf("Case %d:\n",i);
        dfs(0,buff,num);
    }
    return 0;
}
相关TAG标签
上一篇:mac虚拟机安装之后需要做哪些操作让mac使用体验更好?
下一篇:Git创建及合并分支
相关文章
图文推荐

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

版权所有: 红黑联盟--致力于做实用的IT技术学习网站