CF1042B Vitamins

CF1042B Vitamins:

xiu

题目描述

 输入格式

 输出格式

题意翻译 

 输入输出样例

输入 #1

4
5 C
6 B
16 BAC
4 A

输出 #1

15

输入 #2

2
10 AB
15 BA

输出 #2

-1

输入 #3

5
10 A
9 BC
11 CA
4 A
5 B

输出 #3

13

输入 #4

6
100 A
355 BCA
150 BC
160 AC
180 B
190 CA

输出 #4

250

输入 #5

2
5 BA
11 CB

输出 #5

16

  看到奶酪的数据范围就可以想到状压dp,我们先预处理出任意两点之间的距离用dis数组保存,然后枚举状态,由于我们不知道此状态的上一个被吃的奶酪在什么位置,所以要加一维保存上一个奶酪的位置,状态转移方程为f[s][i]=min(f[s][i],f[s-(1<<(i-1))][k]+dis[k][i]);然后在枚举每一个吃最后一个吃的位置(f[maxn-1][i])找到最小的,输出就ok了

Code

#include<bits/stdc++.h>
using namespace std;
int n;
double x[17],y[17];//注意浮点数
double f[1<<17][17];
double dis[17][17];

double sui(double x1,double y1,double x2,double y2){//求两点之间的距离
    return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
}

int main(){
    scanf("%d",&n);
    int maxn=1<<n;
    for(int i=1;i<=n;i++){
        scanf("%lf%lf",&x[i],&y[i]);
        dis[0][i]=dis[i][0]=sui(0.0,0.0,x[i],y[i]);//起点到一点的距离
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            dis[i][j]=sui(x[i],y[i],x[j],y[j]);//任意两点的距离
        }
    }
    for(int i=0;i<maxn;i++){
        for(int j=1;j<=n;j++){
            f[i][j]=1e9;//初始化最大值
        }
    }
    for(int i=1;i<=n;i++){//只吃一个的各个路程
        f[1<<(i-1)][i]=dis[0][i];
    }
    f[0][0]=0;
    for(int s=0;s<maxn;s++){
        for(int i=1;i<=n;i++){
            if(!(s&(1<<(i-1))))continue;//i没有吃,直接跳过
            for(int k=1;k<=n;k++){
                if(k==i||!(s&(1<<(k-1))))continue;//k(上一个点)没吃,或者k等于i(此点),跳过
                f[s][i]=min(f[s][i],f[s-(1<<(i-1))][k]+dis[k][i]);
            }
        }
    }
    double ans=1e9;
    for(int i=1;i<=n;i++){//找最小
        ans=min(ans,f[maxn-1][i]);
    }
    printf("%.2lf",ans);
    return 0;
}
原文地址:https://www.cnblogs.com/LightyaChoo/p/13232552.html