Codeforces Beta Round #8 C. Looking for Order 状压DP,路径记录

题目链接:http://codeforces.com/contest/8/problem/C
题意:平面上有n个物品,这个小朋友会去拿这些物品,然后拿到返回包的位置。但是这个小朋友一次最多拿两个物品,问你怎么去拿,才能使得把所有物品都拿到包的位置,且走的距离和最小
解法: 比较显然的状压,状压中有一个剪枝,显然拿的顺序是随意的,我先拿和后拿都是一样的。所以可以直接return就好了。这题质量感觉蛮高的。。

//CF 8C 状压DP

#include 
using namespace std;
const int maxn = 24;
int dp[1<1<int n, d[maxn+2][maxn+2], x[maxn+2], y[maxn+2];
int dfs1(int x)
{
    if(dp[x]!=-1) return dp[x];
    dp[x] = 1e9;
    for(int i = 0; i < n; i++){
        if(x&(1<int nxt = dfs1(x^(1<if(dp[x] > nxt+d[n][i]+d[i][n]){
                dp[x] = nxt+d[n][i]+d[i][n];
                pre[x]=x^(1<for(int j = i+1; j < n; j++){
                if(x&(1<int nxt = dfs1(x^(1<1<if(dp[x]>nxt+d[n][i]+d[i][j]+d[j][n]){
                        dp[x] = nxt+d[n][i]+d[i][j]+d[j][n];
                        pre[x]=x^(1<1<break;//这个剪枝超级重要,不加会T
        }
    }
    return dp[x];
}
void dfs2(int x){
    if(x){
        for(int i = 0; i < n; i++){
            if((x^pre[x])&(1<printf("%d ",i+1);
            }
        }
        printf("0 ");
        dfs2(pre[x]);
    }
}
int main()
{
    scanf("%d%d", &x[0], &y[0]);
    scanf("%d", &n);
    x[n] = x[0], y[n] = y[0];
    for(int i = 0; i < n; i++){
        scanf("%d%d", &x[i], &y[i]);
    }
    for(int i = 0; i <= n; i++){
        for(int j = 0; j <= n; j++){
            d[i][j] = (x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]);
        }
    }
    memset(dp, -1, sizeof(dp));
    dp[0] = 0;
    int mask = (1<1;
    int ans = dfs1(mask);
    printf("%d\n", ans);
    printf("0 ");
    dfs2(mask);
    printf("\n");
    return 0;
}

你可能感兴趣的:(ACM/ICPC_动态规划,ACM/ICPC_状压dp)