UVALive 4731 Cellular Network
2013-08-02 20:57
337 查看
题目大意:给你n个数,和一个w,每个数的概率是把这个数的值/n个数总值,让你把这些n个数分成w组,每个组的值为这个组加上前面所有组的数字个数之和*这个组的概率之和,要使所有的这些组的和最小。
思路:因为每个组的概率之和前面要乘系数,而且是越早选越小,那么我们把所有数字按照大小,从大到小排序,但由于一个组加进去数字如果过多,它前面的系数也会变大,使前面那些大数去乘一个比较大的系数,这里就需要DP一下。设d[ i ][ j ] 表示前i个区域分成j个组能获得的最小值,状态转移方程为:d[ i ][ j ] = min(d[ i - k - 1 ][ j - 1 ] + sum( i-k ~ i ),k为i与前面几个数一起,0<=k<i )。
代码如下:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int INF = 0x0fffffff ;
const int MAXN = 111 ;
int a[MAXN],sum[MAXN];
int d[MAXN][MAXN];
bool cmp(int a,int b)
{
return a>b;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int n,w;
scanf("%d%d",&n,&w);
sum[0] = 0;
for(int i = 1;i<=n;i++)
{
scanf("%d",&a[i]);
}
sort(a+1,a+n+1,cmp);
for(int i = 1;i<=n;i++)
sum[i] = sum[i-1]+a[i];
for(int i =0;i<=n;i++)
for(int j= 0;j<=max(n,w);j++)
d[i][j] = INF;
d[0][0] = 0;
for(int i = 1;i<=n;i++)
{
for(int j = 1;j<=min(i,w);j++)
{
for(int k = 0;k<i;k++)
{
d[i][j] = min(d[i][j],d[i-k-1][j-1] + (sum[i]-sum[i-k-1])*i);
}
//printf("d[%d][%d] = %d\n",i,j,d[i][j]);
}
}
int ans = INF;
for(int i =1;i<=min(n,w);i++)
ans = min(ans,d
[i]);
printf("%.4f\n",(double)ans/sum
);
}
return 0;
}
思路:因为每个组的概率之和前面要乘系数,而且是越早选越小,那么我们把所有数字按照大小,从大到小排序,但由于一个组加进去数字如果过多,它前面的系数也会变大,使前面那些大数去乘一个比较大的系数,这里就需要DP一下。设d[ i ][ j ] 表示前i个区域分成j个组能获得的最小值,状态转移方程为:d[ i ][ j ] = min(d[ i - k - 1 ][ j - 1 ] + sum( i-k ~ i ),k为i与前面几个数一起,0<=k<i )。
代码如下:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int INF = 0x0fffffff ;
const int MAXN = 111 ;
int a[MAXN],sum[MAXN];
int d[MAXN][MAXN];
bool cmp(int a,int b)
{
return a>b;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int n,w;
scanf("%d%d",&n,&w);
sum[0] = 0;
for(int i = 1;i<=n;i++)
{
scanf("%d",&a[i]);
}
sort(a+1,a+n+1,cmp);
for(int i = 1;i<=n;i++)
sum[i] = sum[i-1]+a[i];
for(int i =0;i<=n;i++)
for(int j= 0;j<=max(n,w);j++)
d[i][j] = INF;
d[0][0] = 0;
for(int i = 1;i<=n;i++)
{
for(int j = 1;j<=min(i,w);j++)
{
for(int k = 0;k<i;k++)
{
d[i][j] = min(d[i][j],d[i-k-1][j-1] + (sum[i]-sum[i-k-1])*i);
}
//printf("d[%d][%d] = %d\n",i,j,d[i][j]);
}
}
int ans = INF;
for(int i =1;i<=min(n,w);i++)
ans = min(ans,d
[i]);
printf("%.4f\n",(double)ans/sum
);
}
return 0;
}
相关文章推荐
- UVALive 4731 Cellular Network(贪心,dp)
- UVALive 4731 Cellular Network
- UVALive 4731 dp+贪心
- uva live 4731 Cellular Network 线性dp
- UVALive 4731 Cellular Network 【dp】
- uva live4731 蜂窝网络 题解(dp+贪心)
- UVaLive 4731 Cellular Network (期望DP)
- UVaLive 4731 UVa 1456 - Cellular Network(概率DP 贪心)
- UVALive 7608 Robot(模拟)
- UVALive 4119 Always an integer (差分数列,模拟)
- UVALive 5905 Pool Construction 最小割,s-t割性质 难度:3
- UVALive 4627 Islands(BFS+并查集)
- UVALive_6606_Meeting Room Arrangement(最大独立集)
- UVALive 7270 Osu! Master(简单水题)
- UVALive 5790 Ball Stacking(灵活转换)
- UVALive - 7457 Discrete Logarithm Problem 费马小定理+暴力枚举+快速幂
- UVALive 6531 Go up the ultras 单调栈+RMQ
- UVALive 5789 双向链表解法
- 【UVALive】2034 - Hot or Cold?(数论)
- UVALive 6449 IQ Test --高斯消元?