NOIP模拟 切木板(贪心)
【题目描述】
有一个 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 1e9+7。
【样例输入】
6 4
2 1 3 1 4
4 1 2
【样例输出】
42
【题目分析】
贪心,易证明先取权值大的边优于取权值小的边。
然后。。。就没有了。。。。(可能我的写法太菜了就被卡常了,emmm,inline是个好东西)
【代码~】
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long LL;
const LL MOD=1e9+7;
const LL MAXN=2e6+10;
inline LL Read()
{
LL i=0,f=1;
char c;
for(c=getchar();(c>'9'||c<'0')&&c!='-';c=getchar());
if(c=='-')
f=-1,c=getchar();
for(;c>='0'&&c<='9';c=getchar())
i=(i<<3)+(i<<1)+c-'0';
return i*f;
}
struct martix{
LL cost;
LL hl; //0为列,1为行
bool operator<(const martix &a)const{ //事实证明重载运算符比cmp要快一点的感觉(然而其他人都用的两个数组啊)
if(cost==a.cost)
return hl<a.hl;
return cost>a.cost;
}
}a[MAXN]; //其实可以开两个数组然后双指针,这样写容易像我第一次交的时候只开了1e6的空间。。。60分滚粗
LL n,m;
int main()
{
scanf("%lld%lld",&n,&m);
for(LL i=1;i<n;++i)
a[i].cost=Read(),a[i].hl=0;
for(LL i=n;i<n+m-1;++i)
a[i].cost=Read(),a[i].hl=1;
sort(a+1,a+n+m);
LL h=1,s=1;
LL ans=0;
for(LL i=1;i<=n+m-2;++i)
{
if(!a[i].hl)
{
ans+=(a[i].cost*s)%MOD;
if(ans>MOD)
ans-=MOD;
h++;
}
else
{
ans+=(a[i].cost*h)%MOD;
if(ans>MOD)
ans-=MOD;
s++;
}
}
printf("%lld",(ans+MOD)%MOD);
return 0;
}

浙公网安备 33010602011771号