• 状压dp Codeforces Beta Round #8 C


    http://codeforces.com/contest/8/problem/C

    题目大意:给你一个坐标系,给你一个人的目前的坐标(该坐标也是垃圾桶的坐标),再给你n个垃圾的坐标,这个人要捡完所有的垃圾,而且每次最多只能捡两个,然后把他扔到垃圾桶里面去。问这个人捡完所有垃圾所需要的最短的路程是多少?(路程=两个坐标之间连线距离的平方)

    思路:貌似是简单的状压dp?

    我们枚举一下1<<n就好了,然后每次都取最高位和其他的某一个进行匹配即可(而不用取其他位,因为其他位在之前就已经枚举过了)。

    //看看会不会爆int!数组会不会少了一维!
    //取物问题一定要小心先手胜利的条件
    #include <bits/stdc++.h>
    using namespace std;
    #define LL long long
    #define ALL(a) a.begin(), a.end()
    #define pb push_back
    #define mk make_pair
    #define fi first
    #define se second
    #define haha printf("haha
    ")
    const int maxn = 24;
    int dp[1 << maxn], par[1 << maxn];
    pair<int, int> girl, a[maxn + 5];
    int n;
    
    inline int get_high(int val){///1需要右移几位
        int pos = 0;
        while (val){
            val >>= 1; pos++;
        }
        return pos - 1;
    }
    
    inline int dis(int x, int y){
        if (x == -1)
            return (girl.fi - a[y].fi) * (girl.fi - a[y].fi) + (girl.se - a[y].se) * (girl.se - a[y].se);
        return (a[x].fi - a[y].fi) * (a[x].fi - a[y].fi) + (a[x].se - a[y].se) * (a[x].se - a[y].se);
    }
    
    int main(){
        ///int high = get_high(4); pos = 2   4 = 100
        scanf("%d%d", &girl.fi, &girl.se);
        cin >> n;
        for (int i = 0; i < n; i++){
            int x, y; scanf("%d%d", &x, &y);
            a[i] = mk(x, y);
        }
        memset(dp, 0x3f, sizeof(dp));
        memset(par, -1, sizeof(par));
        dp[0] = 0;
        for (int i = 1; i < (1 << n); i++){
            int high = get_high(i);///最高位是第几位
            dp[i] = min(dp[i], dp[i ^ (1 << high)] + dis(-1, high) * 2);
            par[i] = i ^ (1 << high);
            for (int j = 0; j < high; j++){
                if (i & (1 << j)) {
                    int tmp = dp[i ^ (1 << j) ^ (1 << high)] + dis(j, high) + dis(-1, j) + dis(-1, high);
                    if (dp[i] > tmp){
                        dp[i] = tmp; par[i] = i ^ (1 << j) ^ (1 << high);
                    }
                }
            }
        }
        printf("%d
    ", dp[(1 << n) - 1]);
        int tmp = (1 << n) - 1;
        printf("0 ");
        for (int i = par[tmp]; i != -1; i = par[i]){
            int val = tmp ^ i;
            int pos = 0;
            while (val){
                if (val & 1) printf("%d ", pos + 1);
                val >>= 1; pos++;
            }
            printf("0 ");
            tmp = i;
        }
        cout << endl;
        return 0;
    }
    View Code
  • 相关阅读:
    oracle基本语句
    java Scanner和异常
    流Stream 文件File 流IO
    java基本方法
    jsp页面展示更加商品的分类,控制商品的显示
    使用jquery select2实现下拉框搜索功能
    JSONObject和JSONArray
    GsonUtils.getGson().fromJson() 转泛型集合用法
    java 实现图片上传功能
    mysql :将其中两个数据的某一个字段合拼成一句
  • 原文地址:https://www.cnblogs.com/heimao5027/p/5990854.html
Copyright © 2020-2023  润新知