小J真爱粉交流群

版权声明:本文是蒟蒻写出来的,神犇转载也要说一声哦! https://blog.csdn.net/WerKeyTom_FTD/article/details/80504712

题目大意

有数字的n*m网格图,DDD和YJQ在玩游戏。
DDD先把一个小人放在第一行某个格子上。获得该格子分数。
接下来每个时刻,YJQ先在任意上下相邻的格子间建墙,可以建任意个。
DDD移动小人向四相邻的位置走(如果没有墙)。并获得新格子分数(重复走重复获得)。
小人到达最后一行游戏结束,现在DDD的目标是最小化,YJQ的目标是最大化,问得分是多少。

做法

可以发现,DDD负责决定在某一行的路线,YJQ会钦点它下哪个洞。
f[i][j]表示从(i,j)这个位置开始到结束的分数。
那么DDD需要决策一条从(i,j)出发,只左右走,经过第i行所有位置的路线,并使得max{fir[k]+f[i+1][k]}最小,其中fir[k]表示第一次到达(i,k)经过的距离。
我们可以做区间dp,g[l,r,0/1]表示路径一个后缀已经决定了,经过了[1,l)以及(r,m]01表示下一个位置去l还是r
那么总复杂度是三方。
详见代码。

#include<cstdio>
#include<algorithm>
#define fo(i,a,b) for(i=a;i<=b;i++)
#define fd(i,a,b) for(i=a;i>=b;i--)
using namespace std;
const int maxn=100+10;
int a[maxn][maxn],f[maxn][maxn],sum[maxn][maxn],g[maxn][maxn][2];
int i,j,k,l,r,mid,t,n,m,mi,ans,ca;
bool czy;
void work(int x){
    int i,j,t;
    fo(i,1,m)
        fo(j,i,m) g[i][j][0]=g[i][j][1]=1000000020;
    g[1][m][0]=g[1][m][1]=0;
    fo(i,1,m)
        fd(j,m,i+1){
            t=max(g[i][j][0],f[x+1][i])+sum[i][i];
            g[i+1][j][0]=min(g[i+1][j][0],t);
            t=max(g[i][j][0],f[x+1][i])+sum[i][j-1];
            g[i+1][j][1]=min(g[i+1][j][1],t);
            t=max(g[i][j][1],f[x+1][j])+sum[j][j];
            g[i][j-1][1]=min(g[i][j-1][1],t);
            t=max(g[i][j][1],f[x+1][j])+sum[i+1][j];
            g[i][j-1][0]=min(g[i][j-1][0],t);
        }
    fo(i,1,m)
        f[x][i]=max(min(g[i][i][0],g[i][i][1]),f[x+1][i])+sum[i][i];
}
int main(){
    freopen("fan.in","r",stdin);freopen("fan.out","w",stdout);
    scanf("%d",&ca);
    while (ca--){
        scanf("%d%d",&n,&m);
        //if (n<=2) continue;
        czy=1;
        fo(i,1,n)
            fo(j,1,m){
                scanf("%d",&a[i][j]);
                if (a[i][j]!=1) czy=0;
            }
        //if (czy&&n>2) continue;
        if (n==1){
            ans=a[1][1];
            fo(j,2,m) ans=min(ans,a[1][j]);
            printf("%d\n",ans);
            continue;
        }
        fo(i,1,m) f[n][i]=a[n][i];
        fd(i,n-1,1){
            fo(j,1,m){
                sum[j][j]=a[i][j];
                fo(k,j+1,m) sum[j][k]=sum[j][k-1]+a[i][k];
            }
            work(i);
        }
        ans=f[1][1];
        fo(j,2,m) ans=min(ans,f[1][j]);
        printf("%d\n",ans);
    }
}
阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页