hdu 5671 Matrix【思维】

Matrix

Time Limit: 3000/1500 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 651    Accepted Submission(s): 276


Problem Description
There is a matrix  M  that has  n  rows and  m  columns  (1n1000,1m1000) .Then we perform  q(1q100,000)  operations:

1 x y: Swap row x and row y  (1x,yn) ;

2 x y: Swap column x and column y  (1x,ym) ;

3 x y: Add y to all elements in row x  (1xn,1y10,000) ;

4 x y: Add y to all elements in column x  (1xm,1y10,000) ;
 

Input
There are multiple test cases. The first line of input contains an integer  T(1T20)  indicating the number of test cases. For each test case:

The first line contains three integers  n m  and  q .
The following  n  lines describe the matrix M. (1Mi,j10,000)  for all  (1in,1jm) .
The following  q  lines contains three integers  a(1a4) x  and  y .
 

Output
For each test case, output the matrix  M  after all  q  operations.

Sample Input
2
3 4 2
1 2 3 4
2 3 4 5
3 4 5 6
1 1 2
3 1 10
2 2 2
1 10
10 1
1 1 2
2 1 2

 


Sample Output
12 13 14 15
1 2 3 4
3 4 5 6
1 10
10 1

题目大意:

一共有四种操作,分别编号为1、2、3、4.对于每种操作:
1、交换x、y两行。

2、交换x、y两列。

3、在x行上边加上y。

4、在x列上边加上y。

输出全部q个操作之后的M矩阵。

分析:因为n、m都不小,而且q也比较大,所以直接暴力模拟是一定一定一定一定会超时的,所以我们尽量使得操作不是q*n。这里我们先把一个矩阵简单化看成只有一个列的矩阵,对其进行这些个操作,比如我们现在有一个5*1的M矩阵row【5】:

1

2

3

4

5

因为每一行都只有一个元素,所以我们直接暴力模拟一下就能够简单操作起来。比如现在要进行:1 2 3的操作,辣么我们直接写代码为这样:

row【2】=row【3】;row【3】=row【2】即可。这样我们类比到一个5*5的矩阵a【5】【5】,其实也可以这样来操作:

1 1 1 1 1

2 2 2 2 2

3 3 3 3 3

4 4 4 4 4

5 5 5 5 5

当我们操作了row【2】=row【3】,row【3】=row【2】的操作的时候,我们看似是操作了一个一维的一个5*1的矩阵的两个元素的交换,其实我们也就可以看成一个行的交换了,当在输出的时候,我们这样输出数据即可:

for(int i=0;i<m;i++)
{
    printf("%d ",a[row[i]][i]);
}
同理我们把这种操作也能够平移到操作列上边,这个时候对于1、2操作的思路就可以构建成这样:


建立一个row【】,建立一个col【】。row【2】=3表示第2行的数据变成了第三行的数据,在输出的时候要输出原来矩阵里边的第三行的数据。col【2】=3表示第二列的数据变成了第三列的数据,在输出的时候要输出原来矩阵里边的第三列数据。


同理我们就可以得到当前行当前列的元素是在原矩阵的哪一个元素。不难理解,可以这样来描述:a【row【i】】【col【j】】表示表示第i行第j列的数据应该输出在原来数据的第row【i】行col【j】列上边的元素。


辣么对于3、4操作其实就更容易操作了,我们不妨将row【i】数组变成row【i】【2】,row【i.】【0】表示row【i】的数据,row【i】【1】表示row【i】这一行的数据上需要加上的数值。这里要注意一点,在操作1、2的时候,注意要将row【】【1】和col【】【1】也进行转移。


这里口述可能说的相对较浅,我们拿出代码对于1、2操作的代码实现:

            if(d==1)
            {
                y--;//y--是因为我开的矩阵是从(0,0)作为左上角开始的
                int tmp=row[x][0];
                int tmp2=row[x][1];
                row[x][0]=row[y][0];//交换行
                row[x][1]=row[y][1];//同时不要忘记了交换增加的数值
                row[y][1]=tmp2;
                row[y][0]=tmp;
            }
            if(d==2)
            {
                y--;
                int tmp=col[x][0];
                int tmp2=col[x][1];
                col[x][0]=col[y][0];//交换列
                col[x][1]=col[y][1];
                col[y][1]=tmp2;
                col[y][0]=tmp;
            }
对于3、4操作的代码实现:

            if(d==3)
            {
                row[x][1]+=y;
            }
            if(d==4)
            {
                col[x][1]+=y;
            }

对于这个题的完整的AC代码:

#include<stdio.h>
#include<string.h>
using namespace std;
int a[1212][1212];
int row[1212][2];
int col[1212][2];
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        memset(a,0,sizeof(a));
        memset(row,0,sizeof(row));
        memset(col,0,sizeof(col));
        int n,m,q;
        scanf("%d%d%d",&n,&m,&q);
        for(int i=0; i<n; i++)row[i][0]=i,row[i][1]=0;
        for(int i=0; i<m; i++)col[i][0]=i,col[i][1]=0;
        for(int i=0; i<n; i++)
        {
            for(int j=0; j<m; j++)
            {
                scanf("%d",&a[i][j]);
            }
        }
        //printf("yes\n");
        while(q--)
        {
            int d,x,y;
            scanf("%d%d%d",&d,&x,&y);
            x--;
            if(d==1)
            {
                y--;
                int tmp=row[x][0];
                int tmp2=row[x][1];
                row[x][0]=row[y][0];
                row[x][1]=row[y][1];
                row[y][1]=tmp2;
                row[y][0]=tmp;
            }
            if(d==2)
            {
                y--;
                int tmp=col[x][0];
                int tmp2=col[x][1];
                col[x][0]=col[y][0];
                col[x][1]=col[y][1];
                col[y][1]=tmp2;
                col[y][0]=tmp;
            }
            if(d==3)
            {
                row[x][1]+=y;
            }
            if(d==4)
            {
                col[x][1]+=y;
            }
            /*
            for(int i=0; i<n; i++)
            {
                int f=0;
                for(int j=0; j<m; j++)
                {
                    if(f!=0)
                    printf(" %d",a[row[i][0]][col[j][0]]+row[i][1]+col[j][1]);
                    else printf("%d",a[row[i][0]][col[j][0]]+row[i][1]+col[j][1]);
                    f++;
                }
                printf("\n");
            }*/
        }
        for(int i=0; i<n; i++)
        {
            int f=0;
            for(int j=0; j<m; j++)
            {
                if(f!=0)
                printf(" %d",a[row[i][0]][col[j][0]]+row[i][1]+col[j][1]);
                else printf("%d",a[row[i][0]][col[j][0]]+row[i][1]+col[j][1]);
                f++;
            }
            printf("\n");
        }
    }
}










  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值