【PA2014】【BZOJ3714】Kuglarz

来源:互联网 发布:女生双肩包推荐 知乎 编辑:程序博客网 时间:2024/05/17 11:05

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
HINT

Source

鸣谢Jcvb

可以考虑差分约束吧
两个点之间连边就是他们的费用,这样之后做MST,很显然是合理的.
为什么我跑的这么慢卧槽..

#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<algorithm>#define MAXN 2010#define LL long longusing namespace std;int n,top,sum;LL ans;int prev[MAXN],f[MAXN];struct edge{    int u,v,w;    bool operator <(const edge& a)const {return w<a.w;}}e[MAXN*MAXN];int find(int x){    return f[x]==x?f[x]:f[x]=find(f[x]);}bool Union(int a,int b){    int x=find(a),y=find(b);    if (x!=y)   {f[x]=y;return 1;}    return 0;}void insert(int u,int v,int w){    e[++top].u=u;e[top].v=v;e[top].w=w;}int main(){    scanf("%d",&n);f[n+1]=n+1;    for (int i=1;i<=n;i++)    {        f[i]=i;int w;        for (int j=i;j<=n;j++)  scanf("%d",&w),insert(i,j+1,w);    }    sort(e+1,e+top+1);    for (int i=1;i<=top;i++)    {        if (Union(e[i].u,e[i].v))   ans+=e[i].w,sum++;        if (sum==n) break;    }    printf("%lld\n",ans);}
0 0
原创粉丝点击