一些在练题遇到的构造题,持续积累中,题解不详尽之处请多多指出。
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=ai−1,j+ai,j−1 找
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;
}
}