列表

详情


NC20146. [JLOI2015]装备购买

描述

脸哥最近在玩一款神奇的游戏,这个游戏里有 n 件装备,每件装备有 m 个属性,用向量zi(aj ,.....,am) 表示  (1 ≤ i ≤ n; 1 ≤ j ≤ m),每个装备需要花费 ci,现在脸哥想买一些装备,但是脸哥很穷,所以总是盘算着怎样才能花尽量少的钱买尽量多的装备。
对于脸哥来说,如果一件装备的属性能用购买的其他装备组合出(也就是说脸哥可以利用手上的这些装备组合出这件装备的效果),那么这件装备就没有买的必要了。
严格的定义是,如果脸哥买了 zi1,.....zip这 p 件装备,那么对于任意待决定的 zh,不存在 b1,....,bp 使得 b1zi1 + ... + bpzip = 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 了。脸哥想要在买下最多数量的装备的情况下花最少的钱,你能帮他算一下吗?

输入描述

第一行两个数 n;m。
接下来 n 行,每行 m 个数,其中第 i 行描述装备 i 的各项属性值。
接下来一行 n 个数,其中 ci 表示购买第 i 件装备的花费。

输出描述

一行两个数,第一个数表示能够购买的最多装备数量
第二个数表示在购买最多数量的装备的情况下的最小花费

示例1

输入:

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

输出:

2 2

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++(g++ 7.5.0) 解法, 执行用时: 292ms, 内存消耗: 4360K, 提交时间: 2023-01-09 16:02:56

#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;

int n,m,cnt=0,val=0,C[505];
long double A[505][505],eps=1e-8;

int main(void)
{
    int min;
    cin>>n>>m;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++) cin>>A[i][j];
    for(int i=1;i<=n;i++) cin>>C[i];
    for(int i=1;i<=m;i++)
    {
        min=0;
        for(int j=cnt+1;j<=n;j++)
            if(fabs(A[j][i])>eps&&(C[j]<C[min]||min==0)) min=j;
        if(min==0) continue;
        cnt++,val+=C[min];
        for(int j=1;j<=m;j++) swap(A[cnt][j],A[min][j]);
        swap(C[cnt],C[min]);      
        for(int j=1;j<=n;j++)
        {
            if(j!=cnt&&fabs(A[j][i])>eps)
            {
                long double rate=A[j][i]/A[cnt][i];
                for(int k=i;k<=m;k++) A[j][k]-=A[cnt][k]*rate;
            }
        }
    }
    cout<<cnt<<' '<<val<<endl;
    return 0;
}

C++14(g++5.4) 解法, 执行用时: 252ms, 内存消耗: 8672K, 提交时间: 2019-08-09 10:04:02

#include <bits/stdc++.h>
using namespace std;
long double const eps = 1e-8;
int const N = 500 + 10;
int n,m,vis[N],ans,cnt;
struct Node
{
	int v;
	long double x[N];
	bool operator < (const Node& e)const{
		return v < e.v;
	}
}a[N],b[N];
int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)
			scanf("%Lf",&a[i].x[j]);
	for(int i=1;i<=n;i++)
		scanf("%d",&a[i].v);
	sort(a+1,a+1+n);
	for(int i=1;i<=n;i++){
		for(int j=m;j>=1;j--){
			if(fabs(a[i].x[j]) > eps){
				if(!vis[j]){   
					vis[j] = true;
					b[j] = a[i];
					ans += a[i].v;
					cnt++;
					break;
				}else{
					long double tmp = a[i].x[j] / b[j].x[j];
					for(int k=j;k>=1;k--){
						a[i].x[k] -= tmp * b[j].x[k];
					}
				}
			}	
		}
	}
	printf("%d %d\n",cnt,ans);
	return 0;
}

C++ 解法, 执行用时: 204ms, 内存消耗: 4348K, 提交时间: 2022-01-01 13:40:42

#include<bits/stdc++.h>
using namespace std;
int n,m,ans,cnt,f[501];
struct M{
    int c;
    long double a[501];
    friend bool operator < (M x,M y){return x.c<y.c;}
}b[501];
int main(){
	cin>>n>>m;
    for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)cin>>b[i].a[j];
    for(int i=1;i<=n;i++)cin>>b[i].c;
    sort(b+1,b+n+1);
	for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)if(fabs(b[i].a[j])>=1e-5){
        if(f[j]){
            long double lala=b[i].a[j]/b[f[j]].a[j];
            for(int k=j;k<=m;k++)b[i].a[k]-=lala*b[f[j]].a[k];
        }
        else{f[j]=i;ans+=b[i].c,cnt++;break;}
    }
	cout<<cnt<<" "<<ans;
    return 0;
}

上一题