Minimum Grid Path
本题来自于codeforces1500分div2的题。
题目大意:在一个平面直角坐标系内,你需要从(0,0)走到(n,n),只能往右或者往上走,而且最多只能转向n-1次。题目给出一个长度为 n 的数组,数组中的每一个数代表每一段(即每一段同向的路程)中 每单位坐标的消耗值。让你计算从(0,0)走到(n,n)的最小消耗值。
思路:由于情况很多也很复杂,且数据范围是 1 0 5 10^5 105恐怕dp也不太合适,所以我采用的思路是,把每种决策都计算出来,然后取最小值就好了。关于每种决策的计算有一个统一的方式,在当前决策中,我们总是让横向和纵向的单位消耗最少的那一步走最多,其他的单位消耗比较多的只走一步,这样就是该决策下的最优解(每一个决策其实是从 1一直到 i 的情况,i从2到依次取)
这里涉及到一个小优化:
因为我们每个决策都要知道我们当前决策的最小值是多少,如果每次都要查找的话未免太过于麻烦,所以我们可以每次都用一个方法预处理出来每个决策中的两个最小值,然后直接用即可。
AC代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<climits>
#define outsum for(int i=1;i<=n;i++)cout<<"i: "<<sum[i]<<endl;
#define outji cout<<"i: "<<i<<" "<<"奇数:"<<ji<<endl;
#define outou cout<<"i: "<<i<<" "<<"偶数:"<<ou<<endl;
#define outoushu for(int i=1;i<=n;i++){cout<<oushu[i]<<" ";}cout<<endl;
#define outjishu for(int i=1;i<=n;i++){cout<<jishu[i]<<" ";}cout<<endl;
using namespace std;
const int N=500010;
typedef long long LL;
int t;
int main()
{
scanf("%d",&t);
while(t--)
{
int n;
scanf("%d",&n);
LL a[N];
LL jishu[N];
LL sum[N];
LL oushu[N];
LL minji=1e18;
LL minou=1e18;
LL ans=0;
for(int i=1;i<=n;i++)
{
scanf("%lld",&a[i]);
sum[i]=sum[i-1]+a[i];
if(i%2==1)
{
if(a[i]<minji)
minji=a[i];
}
else
{
if(a[i]<minou)
minou=a[i];
}
oushu[i]=minou;
jishu[i]=minji;
}
LL minn=1e18;
for(int i=n;i>=2;i--)
{
LL ans=0;
int ji=(i+1)/2;
int ou=i/2;
ans+=sum[i];
ou=n-ou;
ji=n-ji;
ans+=oushu[i]*ou;
ans+=jishu[i]*ji;
if(ans<minn)
minn=ans;
}
printf("%lld\n",minn);
}
return 0;
}
这道题稍微吃一点思维能力。还有优化的方法。
好了,每篇博客都附上一句话。
希望你能在没有我的日子里,能好好学习。