BZOJ 3714: [PA2014]Kuglarz

Time Limit: 20 Sec Memory Limit: 128 MB
Submit: 1560 Solved: 758
[Submit][Status][Discuss]
Description

魔术师的桌子上有n个杯子排成一行,编号为1,2,…,n,其中某些杯子底下藏有一个小球,如果你准确地猜出是哪些杯子,你就可以获得奖品。花费c_ij元,魔术师就会告诉你杯子i,i+1,…,j底下藏有球的总数的奇偶性。
采取最优的询问策略,你至少需要花费多少元,才能保证猜出哪些杯子底下藏着球?
Input

第一行一个整数n(1<=n<=2000)。
第i+1行(1<=i<=n)有n+1-i个整数,表示每一种询问所需的花费。其中c_ij(对区间[i,j]进行询问的费用,1<=i<=j<=n,1<=c_ij<=10^9)为第i+1行第j+1-i个数。
Output

输出一个整数,表示最少花费。
Sample Input
5

1 2 3 4 5

4 3 2 1

3 4 5

2 1

5

Sample Output
7

解题思路

首先可以知道要知道所有的至少要问n次,我们考虑加入一个0点,然后把i整体-1,之后就可以连边跑最小生成树了,否则i与i无法连边。

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define LL long long

using namespace std;
const int MAXN = 2005;

inline int rd(){
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    while(isdigit(ch))  {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
    return x*f;
}

int n,m,c[MAXN][MAXN],cnt,num;
int fa[MAXN];
LL ans;

struct Edge{
    int u,v,w;
}edge[MAXN*MAXN];

int get(int x){
    if(x==fa[x]) return x;
    return fa[x]=get(fa[x]);
}

inline bool cmp(Edge A,Edge B){
    return A.w<B.w;
}

signed main(){
//  freopen("44.in","r",stdin);
    n=rd();
    for(register int i=1;i<=n;i++){
        fa[i]=i;
        for(register int j=i;j<=n;j++){
            edge[++cnt].u=i-1;
            edge[cnt].v=j;
            edge[cnt].w=rd();
        }   
    }
    sort(edge+1,edge+1+cnt,cmp);
    for(register int i=1;i<=cnt;i++){
        int x=get(edge[i].u),y=get(edge[i].v);
        if(x==y) continue;
        num++;fa[x]=y;ans+=edge[i].w;
        if(num==n) break;
    }cout<<ans<<endl;
    return 0;
}
posted @ 2018-08-16 21:54  Monster_Qi  阅读(92)  评论(0编辑  收藏  举报