【2018/09/15】T2-模拟-切木板

版权声明:虽然我只是个小蒟蒻但转载也请注明出处哦 https://blog.csdn.net/weixin_42557561/article/details/82718243

题目描述

有一个 m×n 的矩形木板。你需要把这个木板切成 1×1 的小方块,也就是竖着切 n-1 刀、横着切 m-1 刀。横着切第 i 个位置的权值为 xi ,竖着切第 j 个位置的权值为 yj 。切某一刀时的费用为切这一刀的权值乘上切过的块数。

请你安排切的顺序使得所有费用之和最小。

输入格式

第一行两个数 m,n 。
接下来一行 m-1 个整数 x1,x2,…,xm-1 。
接下来一行 n-1 个整数 y1,y2,…,yn-1 。

输出格式

输出一个数,表示最小的费用之和 mod  109 + 7 。

样例数据 1

输入 

6 4
2 1 3 1 4
4 1 2

输出

42

备注

【数据规模与约定】
对于 30% 的数据, m + n≤10 。
对于 60% 的数据, m,n≤500 。
对于 100% 的数据, 2≤m,n≤106 ;0≤xi,yj≤109 。

【提醒】
建议本题加读入优化。

分析

又是一道水题。。。

我们很容易发现每次都选择权值最大的位置割,最后结果才会是最优

又因为如果都是横着或竖着切,其顺序不影响最后的费用,我们就可以对 x 和 y 分别进行排序,然后用两个指针搞一搞,就over了

又傻逼了的我,想着节约时间,就把相同的权值的统计在一起,然后处理不得当,100分哗哗啦啦的变成20分,呜呜呜呜,下次考试一定要多造数据

代码

注释掉的地方就是考场上写的部分,来组数据有兴趣的同学模拟感受一下我的傻逼:

6 6

4 3 2 1 1 

6 5 4

#include<bits/stdc++.h>
#define in read()
#define P 1000000007
#define N 1000009
#define ll long long
using namespace std;
inline int read(){
	char ch;int res=0;
	while((ch=getchar())<'0'||ch>'9');
	while(ch>='0'&&ch<='9'){
		res=(res<<3)+(res<<1)+ch-'0';
		ch=getchar();
	}
	return res;	
}
int n,m,x[N],y[N];
int main(){
	n=in;m=in;
	int i,j,k;
	for(i=1;i<n;++i) x[i]=in;
	for(i=1;i<m;++i) y[i]=in;
	sort(x+1,x+n);sort(y+1,y+m);
	int heng=0,zong=0;
	ll sum=0;
	i=n-1;j=m-1;x[0]=-1;y[0]=-1;
	while(i&&j){
		/*int tx=1,ty=1;
		while(x[i-1]==x[i]) i--,tx++;
		while(y[j-1]==y[j]) j--,ty++;*/
		if(x[i]==y[j]){
			sum=(sum+1ll*x[i]*(zong+1))%P;
			heng++;
			sum=(sum+1ll*y[j]*(heng+1))%P;
			zong++; 
			i--;j--;
		}
		else{
			if(x[i]>y[j]){
				sum=(sum+1ll*x[i]*(zong+1))%P;
				heng++;
				i--;
			}
			else {
				sum=(sum+1ll*y[j]*(heng+1))%P;
				zong++;
				j--;
			}
		}
	}
	if(!i){
		for(int q=j;q>=1;--q)
			sum=(sum+1ll*y[q]*(heng+1))%P;
	}
	if(!j){
		for(int q=i;q>=1;--q)
			sum=(sum+1ll*x[q]*(zong+1))%P;
	}
	cout<<sum;
	return 0;
}

不要问我为什么又没有第三题,因为……pdf 4 篇的代码,我实在不想敲

猜你喜欢

转载自blog.csdn.net/weixin_42557561/article/details/82718243
今日推荐