好多年没写这种动态规划程序了,最近忽然想起来当年的爱好,写些ACM程序。
这题是个背包问题,然而背包的解法我忘光了。。。
在有AB两个银行时,抢某个银行被抓的概率的计算假设A为pA,B为pB
则p被抓=pA+(1-pA)*pB=pB+(1-pB)*pA
则p不被抓=(1-pA)*(1-pB) 故对输入全部用1减下
2就是这题目要对钱当做体积,求一个当前钱数的不被抓概率
之后就是01背包的过程不再做加法而是乘法了。
之前的我都想明白了,唯一没想明白的是01背包怎么做。。本来01背包一个个物品循环放进DP数组就好了,结果我循环写成了逐个对每个钱的金额来计算最优解,然后优化了下代码,虽然是3个for循环,但是认真算了下时间复杂度,也是n的平方,认真改了几个bug,最后也AC了。
写完之后看看别人的代码http://blog.sina.com.cn/s/blog_6cf509db0100sqgx.html,感觉我这题还是没想好算法就动手了,下次需要注意。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct{
int n;
double value;
}million_s;
#define DP_SIZE 105
million_s million[DP_SIZE][DP_SIZE];
int million_count[DP_SIZE];
int dp[DP_SIZE* DP_SIZE][DP_SIZE];
double dp_p[DP_SIZE*DP_SIZE];
//void qsort(void*base,size_t num,size_t width,int(__cdecl*compare)(const void*,const void*));
int cmp(const void *a, const void *b)
{
if((((million_s *)a)->value < ((million_s *)b)->value))
return 1;
else if((((million_s *)a)->value == ((million_s *)b)->value))
return 0;
else
return -1;
}
int main()
{
int t,i,n,j,k,l;
double max_pro;
int sum, max_m;
double max_p;
int temp_m;
double temp_p;
scanf("%d", &t);
for(i = 0; i < t; i++)
{
scanf("%lf %d", &max_pro, &n);
max_pro = 1 - max_pro;
memset(million_count, 0, sizeof(million_count));//初始化million_count
for(sum = 0, j = 0, max_m = 0; j < n; j++)
{
scanf("%d %lf", &temp_m, &temp_p);
temp_p = 1 - temp_p;
sum += temp_m;
if(temp_m > max_m)
max_m = temp_m;
million[temp_m][million_count[temp_m]].value = temp_p;//temp_m是价值,million_count[temp_m]是价值为temp_m的第几个,million[temp_m][million_count[temp_m]].value是价值为temp_m的概率
million[temp_m][million_count[temp_m]].n = j;//n是价值为temp_m的第几个,从0开始
million_count[temp_m]++;
}
for(j = 0; j < DP_SIZE; j++)
{
qsort(million[j], million_count[j], sizeof(million_s), cmp);//对million[j]排序,按价值从小到大排列
}
for(j = 1; j < DP_SIZE * DP_SIZE; j++)
{
dp_p[j] = 0;//初始化dp
}
dp_p[0] = 1.0;
for(k = 1; k <= sum; k++)
{
memset(dp[k], 0, sizeof(int) * DP_SIZE);
if(k <= max_m)
{
j = 0;
}
else
{
j = k - max_m;
}
max_p = 0;
for(;j < k; j++)
{
for(l = 0; l < million_count[k-j]; l++)
{
if(dp[j][million[k-j][l].n] == 1)
{
continue;
}
temp_p = dp_p[j] * million[k-j][l].value;
if(temp_p > max_p)
{
max_p = temp_p;
dp_p[k] = max_p;
memcpy(dp[k], dp[j], sizeof(int) * DP_SIZE);
dp[k][million[k-j][l].n] = 1;
}
}
}
}
max_m = 0;
for(k = sum; k >= 0; k--)
{
if(dp_p[k] > max_pro)
{
max_m = k;
break;
}
}
printf("%d\n", max_m);
}
return 0;
}