1. 程式人生 > >bzoj 4004 [JLOI2015]裝備購買 擬陣+線性基

bzoj 4004 [JLOI2015]裝備購買 擬陣+線性基

現在 利用 get 證明 span center 沒有 problem 6.5

[JLOI2015]裝備購買

Time Limit: 20 Sec Memory Limit: 128 MB
Submit: 1820 Solved: 547
[Submit][Status][Discuss]

Description

臉哥最近在玩一款神奇的遊戲,這個遊戲裏有 n 件裝備,每件裝備有 m 個屬性,用向量zi(aj ,.....,am) 表示 (1 <= i <= n; 1 <= j <= m),每個裝備需要花費 ci,現在臉哥想買一些裝備,但是臉哥很窮,所以總是盤算著 怎樣才能花盡量少的錢買盡量多的裝備。對於臉哥來說,如果一件裝備的屬性能用購買的其他裝備組合出(也就是 說臉哥可以利用手上的這些裝備組合出這件裝備的效果),那麽這件裝備就沒有買的必要了。嚴格的定義是,如果 臉哥買了 zi1,.....zip這 p 件裝備,那麽對於任意待決定的 zh,不存在 b1,....,bp 使得 b1zi1 + ... + bpzi p = zh(b 是實數),那麽臉哥就會買 zh,否則 zh 對臉哥就是無用的了,自然不必購買。舉個例子,z1 =(1; 2; 3);z2 =(3; 4; 5);zh =(2; 3; 4),b1 =1/2,b2 =1/2,就有 b1z1 + b2z2 = zh,那麽如果臉哥買了 z1 和 z2 就不會再買 zh 了。臉哥想要在買下最多數量的裝備的情況下花最少的錢,你能幫他算一下嗎?

Input

第一行兩個數 n;m。接下來 n 行,每行 m 個數,其中第 i 行描述裝備 i 的各項屬性值。接下來一行 n 個數, 其中 ci 表示購買第 i 件裝備的花費。

Output

一行兩個數,第一個數表示能夠購買的最多裝備數量,第二個數表示在購買最多數量的裝備的情況下的最小花費

Sample Input

3 3
1 2 3
3 4 5
2 3 4
1 1 2

Sample Output

2 2

HINT

如題目中描述,選擇裝備 1 裝備 2,裝備 1 裝備 3,裝備 2 裝備 3 均可,但選擇裝備 1 和裝備 2 的花費最小,為 2。對於 100% 的數據, 1 <= n;m <= 500; 0 <= aj <= 1000。
新加數據三組--2016.5.13

以後再開一篇blog,發現對於線性基不是特別了解,線性基應該是一種概念吧,不是特別清楚

不是針對xor的吧,這裏的話就是和線性基構造方式差不多,如果當前位置有,並且線性基裏沒有,就

加入,否則就減去相當的倍數,用擬陣證明是個極大線性無關組。

 1 #include<cstring>
 2 #include<cmath>
 3 #include<iostream>
 4 #include<algorithm>
 5 #include<cstdio>
 6
7 #define double long double 8 #define eps 0.00001 9 #define N 510 10 using namespace std; 11 inline int read() 12 { 13 int x=0,f=1;char ch=getchar(); 14 while(!isdigit(ch)){if(ch==-)f=-1;ch=getchar();} 15 while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-0;ch=getchar();} 16 return x*f; 17 } 18 19 int n,m,ans,num; 20 int vis[N]; 21 struct Node 22 { 23 double b[N]; 24 int val; 25 }a[N]; 26 27 bool cmp(Node x,Node y){return x.val<y.val;} 28 int main() 29 { 30 n=read(),m=read(); 31 for (int i=1;i<=n;i++) 32 for (int j=1;j<=m;j++) 33 scanf("%Lf",&a[i].b[j]); 34 for (int i=1;i<=n;i++) a[i].val=read(); 35 sort(a+1,a+n+1,cmp); 36 for (int i=1;i<=n;i++) 37 for (int j=1;j<=m;j++) 38 if (fabs(a[i].b[j])>eps) 39 { 40 if (!vis[j]) 41 { 42 vis[j]=i; 43 ans+=a[i].val; 44 num++; 45 break; 46 } 47 else 48 { 49 double t=(double)a[i].b[j]/(double)a[vis[j]].b[j]; 50 for (int k=j;k<=m;k++) 51 a[i].b[k]-=t*a[vis[j]].b[k]; 52 } 53 } 54 printf("%d %d\n",num,ans); 55 }

bzoj 4004 [JLOI2015]裝備購買 擬陣+線性基