zhber
有好多做过的题没写下来,如果我还能记得就补吧

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

 

把杯子根据有没有球看成0/1的序列,题意是可以询问一段区间的和,要求确定每一个点的状态数

显然要一直取到长度为1的区间,才能确定这个点。

考虑把原来的序列划分成一些连续的区间,只要求出每一段的最小代价加上这样划分的代价就好了

这样变成不停的在序列上划分。显然每次划分都使得区间数+1,最终必须划分成n个长度为1的区间,因为要知道每一个点的状态

这样一来只需要考虑划分成n-1个区间的最小代价就好了

但是实际上划分的顺序对答案是不影响的,而且显然划分成n-1个区间就相当于连n-1条线

所以变成最小生成树了……真神奇

另外……因为a[i][j]实际上是把区间[i-1,j]提出来的代价,所以应该求0到n一共n+1个点的最小生成树

听说prim加个堆优化能跑得飞快,但是还没打,就写了个很sb的n^2prim

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstring>
 4 #include<cstdlib>
 5 #include<algorithm>
 6 #include<cmath>
 7 #include<queue>
 8 #include<deque>
 9 #include<set>
10 #include<map>
11 #include<ctime>
12 #define LL long long
13 #define inf 2147483647
14 #define pa pair<int,int>
15 #define pi 3.1415926535897932384626433832795028841971
16 #define N 2010
17 using namespace std;
18 int a[N][N];
19 int near[N];
20 bool mrk[N];
21 int n;
22 LL ans;
23 inline LL read()
24 {
25     LL x=0,f=1;char ch=getchar();
26     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
27     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
28     return x*f;
29 }
30 inline void prim()
31 {
32     mrk[0]=1;
33     for(int i=1;i<=n;i++)
34       near[i]=a[0][i];
35     for (int i=1;i<=n;i++)
36     {
37         int mn=inf,fnd=0;
38         for (int j=1;j<=n;j++)
39           if (!mrk[j]&&near[j]<mn)
40           {
41             mn=near[j];
42             fnd=j;
43           }
44         ans+=mn;
45         mrk[fnd]=1;
46         for (int j=1;j<=n;j++)
47           if (!mrk[j]) near[j]=min(near[j],a[fnd][j]);
48     }
49 }
50 int main()
51 {
52     n=read();
53     for (int i=1;i<=n;i++)
54     for (int j=i;j<=n;j++)
55       a[i-1][j]=a[j][i-1]=read();
56     prim();
57     printf("%lld\n",ans);
58 }
bzoj3714

 

posted on 2014-10-27 21:20  zhber  阅读(667)  评论(0编辑  收藏  举报