zoukankan      html  css  js  c++  java
  • D. Three Pieces(dp,array用法,棋盘模型)

    https://codeforces.com/contest/1065/problem/D

    题意

    给你一个方阵,里面的数字从1~nn,你需要从标号为1的格子依次走到标号为nn,在每一个格子你有两个决策:
    1.换工具(车,马,象)
    2.不换工具,继续走
    换工具本身算作一步,问最少需要多少步才能完成目标,要是步数相同,需要换工具步数最小

    思路

    思路十分明确,每个格子有三个状态,处理出每个格子每个状态之间的最小步,然后从编号为1的格子进行dp,答案就是
    min(dp[id[n]][0~2])

    处理

    这道题难在处理

    • 怎么保证状态编号唯一

    首先将二维坐标一维化,因为每个位置有三种状态等于加了一维上去,所以要将一维化的坐标*3,再加上0~2,每一个格子每一种状态就形成唯一的编号

    • 怎么处理车,马,象

    车:ip||jq
    马: abs(i-p)+abs(j-q)3
    象:i+j
    p+q||i-j==p-q
    需要注意的是,一定要用if else if 并且注意判断顺序(先判车后判马),因为对于车的判定有的马会在里面,所以必须得先把车给判掉

    • 关于答案的计算

    学了一下array,可以直接比较(按下标逐个比),可以重载运算符
    还有memset可以初始化结构体,1大概是1e7

    #include<bits/stdc++.h>
    #define inf 0x3f3f3f3f
    #define M 505
    using namespace std;
    array<int,2> f[M][M],dp[M][5],ans;
    int n,i,j,k,a[M],p,q,x,y;
    int id(int x,int y){return (x*n+y)*3;}
    
    array<int,2> operator+(const array<int,2> a,const array<int,2> b){
        return {a[0]+b[0],a[1]+b[1]};
    }
    
    int main(){
        cin>>n;
        for(i=0;i<n*n;i++){cin>>x;a[x]=i;}   
        memset(f,1,sizeof(f));memset(dp,1,sizeof(dp));
    
        for(i=0;i<n;i++){
            for(j=0;j<n;j++){
                for(p=0;p<3;p++)for(q=0;q<3;q++){
                   x=id(i,j);
                   f[x+p][x+q]={1,1};
                } 
                for(p=0;p<n;p++){
                    for(q=0;q<n;q++){
                       x=id(i,j);y=id(p,q);
                       if(p==i||q==j)f[x][y]={1,0};
                       else if(abs(i-p)+abs(j-q)==3)f[x+1][y+1]={1,0};
                       else if(p+q==i+j||p-q==i-j)f[x+2][y+2]={1,0};
                    }
                }
            }
        }
        for(k=0;k<3*n*n;k++)for(i=0;i<3*n*n;i++)for(j=0;j<3*n*n;j++)f[i][j]=min(f[i][j],f[i][k]+f[k][j]);
    
        dp[1][0]=dp[1][1]=dp[1][2]={0,0};
        for(i=2;i<=n*n;i++){
            q=a[i]*3;p=a[i-1]*3;
            for(j=0;j<3;j++)
                for(k=0;k<3;k++)
                    dp[i][j]=min(dp[i][j],dp[i-1][k]+f[p+k][q+j]);
        }
        ans=min(dp[n*n][0],min(dp[n*n][1],dp[n*n][2]));
        cout<<ans[0]<<" "<<ans[1];
    }
    
    
    
  • 相关阅读:
    E. XOR and Favorite Number (莫队板子题)
    bzoj 2038: [2009国家集训队]小Z的袜子(hose)
    世风日下的哗啦啦族I (简单分块模板)
    Turtles (非纯分块)
    楼房重建
    智商问题
    A
    51 Nod 1640 天气晴朗的魔法( Kruskall )
    后缀数组
    51nod 1562 玻璃切割 (set)
  • 原文地址:https://www.cnblogs.com/VIrtu0s0/p/9940527.html
Copyright © 2011-2022 走看看