【补题记录】构造题(持续更新)

一些在练题遇到的构造题,持续积累中,题解不详尽之处请多多指出。

HDU5015 矩阵快速幂(构造矩阵)

题意:

a 0 , m = 2333... a_{0,m}=2333... a0,m=2333... a n , 0 = 输入的值 a_{n,0}=输入的值 an,0=输入的值
然后 a i , j = a i − 1 , j + a i , j − 1 a_{i,j}=a_{i-1,j}+a_{i,j-1} ai,j=ai1,j+ai,j1 a n , m a_{n,m} an,m

思路

思路来源
构造矩阵,相乘

0 233 2333… ->每次10+3
a1 a1+233
a2 a1+a2+233
a3 a1+a2+a3+233

构造(借鉴别人思路)
(23,a1,a2,a3,3)
10 10 10 …0
0 1 1 … 0
0 0 1 0
0 0 0 0
1 1 1 1
=(233,233+a1,233+a1+a2,…,3)//最后一个值保持为三 在找下一列时能+3
//每次求一列就乘个构造出来的矩阵(需要求矩阵的幂)

HDU5402(构造路径)

从左上角走到右下角

分讨

  • n,m其中一个是奇数 问题不大 都遍历一遍的最优值
  • n,m都是偶数 不能都遍历一遍 因为每一行都直来直往会到左下
    在这里插入图片描述

换条路 发现最少要舍弃一个
在这里插入图片描述

要舍弃哪一个?

在这里插入图片描述
多次画图发现绕过(i+j)%2==1 在这些里面找最小的

怎么绕?

  • i是偶数
    在这里插入图片描述
    (当然也可能是下图这样,不过这样不好找共性,上图共性是最后一行从左向右直着向end
    在这里插入图片描述
  • i是奇数
    在这里插入图片描述

代码

void solve(){
    int n,m;
    while (cin>>n>>m)
    {
        vector<vector<int>>a(n+5,vector<int>(m+5));
        int sum=0,minn=1e9,minx,miny;
        forr(i,1,n){
            forr(j,1,m){
                cin>>a[i][j];
                sum+=a[i][j];
                if((i+j)%2&&a[i][j]<minn)minn=a[i][j],minx=i,miny=j;
            }
        }

        string ans;
        if(n&1){//n是奇数
            forr(i,1,n){
                forr(j,1,m-1){
                    if(i&1)ans+="R";
                    else ans+="L";
                }
                if(i!=n)ans+="D";
            }
        }else if(m&1){//m是奇数
            forr(i,1,m){
                forr(j,1,n-1){
                    if(i&1)ans+="D";
                    else ans+="U";
                }
                if(i!=m)ans+="R";
            }
        }
        //n,m都不是奇数
        else{
            sum-=minn;
            int r=1;//行数
            while(1){//停在要绕的行
                if(minx%2&&r==minx)break;//min在奇数行 方向:左->右  停在本行 从下面绕
                if(!(minx%2)&&r+1==minx)break;//min在偶数行 停在上一行 从上面绕
                forr(i,1,m-1){
                    if(r%2)ans+="R";//奇数行方向:左->右
                    else ans+="L";//偶数行:右->左
                }
                ans+="D";
                r++;
                //cout<<r<<' ';
            }
            //绕的操作
            int nx=r,ny=1;
            if(minx%2)//奇数行
            {
                while ((ny+1)<miny){
                    ans+="DRUR";
                    ny+=2;
                }
                ans+="DR",ny++;
                while(ny<m)ans+="RURD",ny+=2;
            }else{//偶数行
                while ((ny+1)<miny)
                {
                    ans+="DRUR";
                    ny+=2;
                }
                ans+="RD",ny++;
                while (ny<m)ans+="RURD",ny+=2;
            }
            r++;
            //cout<<r<<' ';
            while (r<n)
            {
                
                ans+="D";
                r++;
                //cout<<r<<' ';
                forr(i,1,m-1){
                    if(r&1)ans+="L";
                    else ans+="R";
                }
                if(r==n)break;
            }
        }
        cout<<sum<<' '<<ans<<endl;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值