11.23A组 T2----path
Solution
有一条路径全为0,显然考虑将其置于边界处,暂定为第1行与第n列。
然后从小到大考虑每条路径的位置:
权为1的路径显然要与0有许多重合的位置,权为2~(n-1)的类似。
容易有这样的构造方式:从上到下,每行又从右到左地考虑每个位置填什么。
那么当前已填数能走出的最大权值+1就是经过当前要填的数能走出的最小权值。
由于往右再往下走一定最小,往下再往右一定最大,则通过前缀和以及上式可以快速算出每个格子的值。
发现构造过程时刻满足所有可能路径的权不同,因此构造方式合法。
Review
通过权值可能为0迅速找到突破口,很快就解决了。
是道不错的思考题。
原题解按每条斜对角线的顺序构造。其他大佬还有更简洁的递推关系式。
code
#include<cstdio>
using namespace std;
int n;
struct node{
int a[65],w;
inline void print()
{
for (int i=w-1;i>=0;--i)printf("%d",a[i]);
putchar(' ');
}
}ze,mx,one;
node operator +(node A,node B)
{
if (A.w<B.w)A.w=B.w;
for (int i=0;i<A.w;++i)
{
if ((A.a[i]+=B.a[i])>9)
{
A.a[i]-=10;
++A.a[i+1];
}
}
if (A.a[A.w])++A.w;
return A;
}
node operator -(node A,node B)
{
for (int i=0;i<A.w;++i)
{
if ((A.a[i]-=B.a[i])<0)
{
A.a[i]+=10;
--A.a[i+1];
}
}
while (A.w>1&&!A.a[A.w-1])--A.w;
return A;
}
node A[105][105],B[105],C[105],D;
int main()
{
freopen("path.in","r",stdin);
freopen("path.out","w",stdout);
scanf("%d",&n);
ze.w=1;
one.w=one.a[0]=1;
mx=ze;
for (int i=1;i<=n;++i)A[1][i]=A[i][n]=B[i]=C[i]=ze;
for (int i=2;i<=n;++i)
{
D=ze;
for (int j=n-1;j;--j)
{
A[i][j]=mx+one-B[j]-D;
B[j]=B[j]+A[i][j];
D=D+A[i][j];
mx=mx+A[i][j]-A[i-1][j+1];
}
}
for (int i=1;i<=n;++i)
{
for (int j=1;j<=n;++j)
A[i][j].print();
puts("");
}
return 0;
node max=ze;
for (int i=2;i<=n;++i)
{
max=max+A[i][1]+A[n][i];
}
max.print();
return 0;
}