Buildings
Time Limit: 5000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 6224 Accepted Submission(s): 2232
The public opinion is that Guanghua Building is nothing more than one of hundreds of modern skyscrapers recently built in Shanghai, and sadly, they are all wrong. Blue.Mary the great civil engineer had try a completely new evolutionary building method in project of Guanghua Building. That is, to build all the floors at first, then stack them up forming a complete building.
Believe it or not, he did it (in secret manner). Now you are face the same problem Blue.Mary once stuck in: Place floors in a good way.
Each floor has its own weight wi and strength si. When floors are stacked up, each floor has PDV(Potential Damage Value) equal to (Σwj)-si, where (Σwj) stands for sum of weight of all floors above.
Blue.Mary, the great civil engineer, would like to minimize PDV of the whole building, denoted as the largest PDV of all floors.
Now, it’s up to you to calculate this value.
In each test case, in the first line is a single integer N (1 <= N <= 105) denoting the number of building’s floors. The following N lines specify the floors. Each of them contains two integers wi and si (0 <= wi, si <= 100000) separated by single spaces.
Please process until EOF (End Of File).
If no floor would be damaged in a optimal configuration (that is, minimal PDV is non-positive) you should output 0.
3
1
思路:
我们要求解的是正整数的最大值的最小,只要保证每次可能出现正数时他是可能取值里面最小的即可。假设n个板块一个都没有选时,压在地面上的总重量为 S=p[1].w + p[2].w+...+p[n].w。首先我们选择
最下面那个板块,它的PDV = S-Wi-Si = S-(Wi+Si), 此时我们只要保证(Wi+Si)值最大,就可选取PDV最小的。最下面一个选择之后,剩下的板块中再进行选择时,原理相同。依此类推,每次选择S'-(Wi+Si)最小(其实就是(Wi+Si)最大)。
综上,贪心策略: 每次选择“Wi+Si”值最大m的那个板。
------------------------------------------------------------------------
这题p[0]是最下面的板
上面是老师给的 但是我自己比较迷惑 我不明白为什么把Wi+Si排序这样就是最优序列了 我真的想了好久好久也没整明白 我现在有个想法就是 不知道对不对 因为在最上面的∑Wj最小 ,所以Wi+Si可以最小,而越下面的它的∑Wj就越大,所以要尽量让Wi+Si小一点,他才能整体达到最优。但是这样子去看老师的思路,好像又不是这个意思,我也不知道了啊啊,下次课上去问下老师吧。
#include<stdio.h>
#include<stdlib.h>
#define MAXN 100005
struct node
{
int s,w;
int sum;
}p[MAXN];
//比较器,回调函数
/*比较器最规范的写法
int cmp( const void *a, const void *b)
{
struct node *x = (struct node *)a;
struct node *y = (struct node *)b;
return y->sum - x->sum;
}
*/
int cmp( struct node *a, struct node *b)
{
return b->sum - a->sum;
}
int main()
{
//文件输入/输出
//这样可以把输入输出数据分开 方便查看
//freopen("din.txt","r",stdin);
//freopen("dout.txt","w",stdout);
int n,i;
while( scanf("%d",&n)!=EOF)
{
__int64 s=0; //所有板块重量之和
//输入n个楼层
for(i=0;i<n;i++)
{
scanf("%d%d",&p[i].w,&p[i].s);
p[i].sum = p[i].w + p[i].s;
s += p[i].w;
}
//对所有石板按sum值排序-->优先队列
qsort(p,n,sizeof(p[0]),cmp);
//题解:在最优叠放方式下(由前面的贪心保证),所有“正值PDV”中的“最大值”, PDV=s-w[i]-s[i]
__int64 ans=0;//所有楼层PDV的最大值
for(i=0;i<n;i++)
{
s -=p[i].w;//剩下板块的总重量,下一次板块选择时要用
__int64 tmp = s-p[i].s;//第i层板块的PDV值
if(tmp>0)
ans = ans>tmp ? ans : tmp;
}
printf("%I64d\n",ans);
}
//fclose(stdin);
//fclose(stdout);
return 0;
}