2 条题解

  • 0
    @ 2025-10-8 16:52:09

    代码by gn,题解by hansang:

    #include<bits/stdc++.h>
    using namespace std;
    const int N=15;
    char s[N];
    struct node{int x, y;} a[N], b[N];
    int lena, lenb, dp[N][1<<N], f[N][N][1<<N];
    //a数组存骑士方位,b数组存人质,dp[i][j]表示当前移动骑士i俘获了j集合的人质
    //f[x][y][S]表示S集合中一条终点为(x, y)的最短路径
    int get_dis(node n1, node n2){
        return max(abs(n1.x-n2.x), abs(n1.y-n2.y));
        //因为可以走八个方向,所以这样求最短距离
    }
    int calc(node no, int S){ //使用记忆化搜索
        int x=no.x, y=no.y;
        if(f[x][y][S]>=0) return f[x][y][S];
        if(S==0) return f[x][y][S]=0;
        int res=1e9;
        for(int i=1; i<=lenb; i++) if((1<<(i-1))&S){
            res=min(res, calc(b[i], S^(1<<(i-1)))+get_dis(no, b[i]));
            //从S集合中再挑一个点,先求S集合中一条终点为那个点的最短路径,再加上那个点到当前点的距离
        }
        return f[x][y][S]=res;
    }
    int main(){
        int T; scanf("%d", &T);
        while(T--){
            lena=lenb=0; //多组数据清0很重要
            for(int i=1; i<=8; i++){
                scanf("%s", s+1);
                for(int j=1; j<=8; j++){if(s[j]=='K') a[++lena]={i, j}; 
                    if(s[j]=='P') b[++lenb]={i, j};
                }
            }
    
            memset(dp, 0x3f, sizeof(dp));
            memset(f, -1, sizeof(f));
            for(int i=0; i<(1<<lenb); i++) 
                dp[1][i]=calc(a[1], i); //骑士1特殊赋值
    
            for(int i=2; i<=lena; i++){
                for(int j=0; j<(1<<lenb); j++){
                    for(int k=0; k<(
    • 0
      @ 2025-10-8 16:51:57

      代码by gn,题解by hansang:

      #include<bits/stdc++.h>
      using namespace std;
      const int N=15;
      char s[N];
      struct node{int x, y;} a[N], b[N];
      int lena, lenb, dp[N][1<<N], f[N][N][1<<N];
      //a数组存骑士方位,b数组存人质,dp[i][j]表示当前移动骑士i俘获了j集合的人质
      //f[x][y][S]表示S集合中一条终点为(x, y)的最短路径
      int get_dis(node n1, node n2){
          return max(abs(n1.x-n2.x), abs(n1.y-n2.y));
          //因为可以走八个方向,所以这样求最短距离
      }
      int calc(node no, int S){ //使用记忆化搜索
          int x=no.x, y=no.y;
          if(f[x][y][S]>=0) return f[x][y][S];
          if(S==0) return f[x][y][S]=0;
          int res=1e9;
          for(int i=1; i<=lenb; i++) if((1<<(i-1))&S){
              res=min(res, calc(b[i], S^(1<<(i-1)))+get_dis(no, b[i]));
              //从S集合中再挑一个点,先求S集合中一条终点为那个点的最短路径,再加上那个点到当前点的距离
          }
          return f[x][y][S]=res;
      }
      int main(){
          int T; scanf("%d", &T);
          while(T--){
              lena=lenb=0; //多组数据清0很重要
              for(int i=1; i<=8; i++){
                  scanf("%s", s+1);
                  for(int j=1; j<=8; j++){
                      if(s[j]=='K') a[++lena]={i, j}; 
                      if(s[j]=='P') b[++lenb]={i, j};
                  }
              }
      
              memset(dp, 0x3f, sizeof(dp));
              memset(f, -1, sizeof(f));
              for(int i=0; i<(1<<lenb); i++) 
                  dp[1][i]=calc(a[1], i); //骑士1特殊赋值
      
              for(int i=2; i<=lena; i++){
                  for(int j=0; j<(1<<lenb); j++){
                      for(int k=0; k<(1<<lenb); k++) if((j&k)==k){
                          int t=calc(a[i], j^k);
                          dp[i][j]=min(dp[i][j], dp[i-1][k]+t);
                          //分成两部分,一部分在上一个骑士解决,一部分当前骑士走
                      }
                  }
              }
              printf("%d\n", dp[lena][(1<<lenb)-1]);
          }
          return 0;
      }
      • 1

      信息

      ID
      544
      时间
      1000ms
      内存
      128MiB
      难度
      8
      标签
      递交数
      20
      已通过
      7
      上传者