• LightOJ1057 Collecting Gold(状压DP)


    这道题可以想到几点:

    • 整个行程可以看作一次次的行走,每次行走都是用最短的路程从某一非空点到达另外一非空点;
    • 两点间最少的步数是二者x和y坐标差的最大值;
    • 返回原点这个过程,肯定是取完最后一个黄金后直接用最少的步数从这儿出发回到原点。

    然后就是状压DP了:

    dp[u][S]:经过非空点集S后到达u点最少的步数

    转移就枚举从哪儿到达u点的。

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 using namespace std;
     5 #define INF (1<<29)
     6 int x[16],y[16],cnt;
     7 int d[16][1<<16];
     8 int main(){
     9     int t,n,m;
    10     scanf("%d",&t);
    11     for(int cse=1; cse<=t; ++cse){
    12         scanf("%d%d",&n,&m);
    13         cnt=0;
    14         char c;
    15         int sx,sy;
    16         for(int i=0; i<n; ++i){
    17             for(int j=0; j<m; ++j){
    18                 scanf(" %c",&c);
    19                 if(c=='x') sx=i,sy=j;
    20                 else if(c=='g') x[cnt]=i,y[cnt]=j,++cnt;
    21             }
    22         }
    23         x[cnt]=sx,y[cnt]=sy,++cnt;
    24 
    25         for(int i=0; i<16; ++i){
    26             for(int j=0; j<(1<<16); ++j) d[i][j]=INF;
    27         }
    28         d[cnt-1][1<<cnt-1]=0;
    29         for(int i=(1<<cnt-1)+1; i<(1<<cnt); ++i){
    30             for(int j=0; j<cnt; ++j){
    31                 if(((i>>j)&1)==0 || j==cnt-1) continue;
    32                 for(int k=0; k<cnt; ++k){
    33                     if(((i>>k)&1)==0 || k==j) continue;
    34                     d[j][i]=min(d[j][i],d[k][i^(1<<j)]+max(abs(x[j]-x[k]),abs(y[j]-y[k])));
    35                 }
    36             }
    37         }
    38         int res=INF;
    39         for(int i=0; i<cnt; ++i) res=min(res,d[i][(1<<cnt)-1]+max(abs(x[i]-x[cnt-1]),abs(y[i]-y[cnt-1])));
    40         printf("Case %d: %d
    ",cse,res);
    41     }
    42     return 0;
    43 }
  • 相关阅读:
    第16周作业
    第15周作业
    迟到的第14周作业
    第13次作业集
    软件工程结课总结
    第13次作业
    第12次作业
    第11次作业--字符串的处理
    第10次作业(2)
    第十次作业
  • 原文地址:https://www.cnblogs.com/WABoss/p/5133794.html
Copyright © 2020-2023  润新知