#include <malloc.h>
struct fishingOP {
int maxFishing;
int stayInterval;
};
typedef struct fishingOP fishingOP;
void getMostFish(int * fi, int * di, int * ti, int lakeNum, int intervalNum) {
fishingOP ** matrix = (fishingOP **)malloc(sizeof(fishingOP *) * lakeNum);
for (int i = 0; i < lakeNum; i++) {
*(matrix + i) = (fishingOP *)malloc(sizeof(fishingOP) * (intervalNum + 1));
}
for (int i = 0; i < lakeNum; i++) {
for (int j = 0; j < intervalNum + 1; j++) {
matrix[i][j].maxFishing = -1;
}
}
for (int i = lakeNum-1; i >= 0; i--) {
for (int j = 0; j < intervalNum + 1; j++) {
if (j == 0) { // no time to fishing
// printf("%d %d 0\n", i, j);
matrix[i][j].maxFishing = 0;
matrix[i][j].stayInterval = 0;
continue;
} else if (i == lakeNum-1 && j == 1) { // can only fishing from the last lake, and only 1 interval
matrix[i][j].maxFishing = fi[i];
// printf("%d %d %d\n", i, j, matrix[i][j].maxFishing);
matrix[i][j].stayInterval = 1;
continue;
} else if (i == lakeNum-1 && j >= 1) { // can only fishing from the last lake, stay more than 1 interval
if (fi[i] - di[i] *(j - 1) > 0) {
matrix[i][j].maxFishing = matrix[i][j-1].maxFishing + fi[i] - di[i] *(j-1);
} else {
matrix[i][j].maxFishing = matrix[i][j-1].maxFishing; // if have stay, but no fish, of course equals previuos interval
}
matrix[i][j].stayInterval = j;
// printf("%d %d %d\n", i, j, matrix[i][j].maxFishing);
continue;
} else {
int stayInterval = 0;
if (j - ti[i] < 0) { // no time to next lake
int fishNumCurLakeAcc = 0;
int fishIntervalNum = fi[i];
for (int k = 1; k <= j; k++) { // iterate all possible stay interval num
fishNumCurLakeAcc += fishIntervalNum;
fishIntervalNum -= di[i];
if (fishIntervalNum < 0) {
fishIntervalNum = 0;
}
}
matrix[i][j].maxFishing = fishNumCurLakeAcc;
stayInterval = j;
matrix[i][j].stayInterval = stayInterval;
} else { // still have time to go next lake, so can fish some time here.
int maxfishingNum = matrix[i+1][j - ti[i]].maxFishing; // no fishing in lake i.
int fishNumCurLakeAcc = 0;
int fishIntervalNum = fi[i];
for (int k = 1; k <= j; k++) { // iterate all possible stay interval num
fishNumCurLakeAcc += fishIntervalNum;
int curFishNum;
if (j - k - ti[i] >= 0) {
curFishNum = fishNumCurLakeAcc + matrix[i+1][j - k - ti[i]].maxFishing;
} else {
curFishNum = fishNumCurLakeAcc;
}
fishIntervalNum -= di[i];
if (fishIntervalNum < 0) {
fishIntervalNum = 0;
}
if (curFishNum >= maxfishingNum) {
maxfishingNum = curFishNum;
stayInterval = k;
}
}
matrix[i][j].maxFishing = maxfishingNum;
matrix[i][j].stayInterval = stayInterval;
}
// printf("%d %d %d stay: %d\n", i, j, matrix[i][j].maxFishing, matrix[i][j].stayInterval*5);
}
}
}
int i = 0;
int j = intervalNum;
bool firstTime = 1;
while(1) {
if (i == lakeNum) {
break;
}
if (!firstTime) {
printf(", ");
} else {
firstTime = 0;
}
int stayInterval;
if (j >= 0) {
stayInterval = matrix[i][j].stayInterval;
} else {
stayInterval = 0;
}
printf("%d", stayInterval*5);
j = j - stayInterval - ti[i];
i = i + 1;
}
printf("\n");
printf("Number of fish expected: %d\n\n", matrix[0][intervalNum].maxFishing);
for (int i = 0; i < lakeNum; i++) {
free(*(matrix + i));
*(matrix + i) = NULL;
}
free(matrix);
matrix = NULL;
}
int main() {
while(1) {
int lakeNum = 0;
int hour = 0;
scanf("%d", &lakeNum);
if (lakeNum == 0) {
break;
}
scanf("%d", &hour);
int intervalNum = hour*12;
int * fi = (int *)malloc(sizeof(int) * lakeNum);
int * di = (int *)malloc(sizeof(int) * lakeNum);
for (int i = 0; i < lakeNum; i++) {
scanf("%d", fi+i);
}
for (int i = 0; i < lakeNum; i++) {
scanf("%d", di+i);
}
int * ti = (int *)malloc(sizeof(int) * (lakeNum-1));
for (int i = 0; i < lakeNum-1; i++) {
scanf("%d", ti + i);
}
getMostFish(fi, di, ti, lakeNum, intervalNum);
free(fi);
fi = NULL;
free(di);
di = NULL;
free(ti);
ti = NULL;
}
}
DP, 变种背包, 只不过是每件物品有多个数量的背包, 并且还要注意lake在全部钓完鱼以后,继续掉就不能再减di。
上面用了二维数组
matix【i】【j】 代表的是从第i个lake开始, 总共有j个interval(5分钟)情况下的 能钓到的最多鱼。
考虑的情况有:
<1> j == 0, 没有时间钓鱼了, 那么最大鱼数为0
<2> i == lakeNum, 从最后一个lake开始钓, 那最大鱼数就是从此lake能钓到的所有鱼。
<3> j 不足以 跑到下一个lake, 那么就只能在lake钓, 最大鱼数就是在j的时间内能钓的最多鱼
<4> j还可以跑到下一个lake, 那么就可以再分了, 在此lake停留一些时间(1 ~ j),
比较每种停留时间下能钓到的最大鱼数。(多个选择, 和0-1背包的区别, 0-1背包每个物品只有一件)
注意这里也用两种情况:
(1) 停留了K, 剩下的时间还能跑到下一个lake, 那么鱼数 就是 这k段时间里钓到的鱼 加上 matix[i+1][j -k - 到下一个lake花的时间]
(2)停留K, 但是剩下时间不够到下一个lake, 那么最大鱼数就是这j段时间在第i个lake能钓到的鱼.
其实一个三维的数组更方便
matix[i][j][k] 代表 从第i个lake开始, 总共由 j 个interval, 并且在 第i个lake 钓 k 段时间的最大鱼数.
本题还可以用贪心法, 以后补上.
为了方便追踪轨迹, 除了记录每个情况的最大鱼数, 还记录了停留的时间.
DP在实际编写的时候, 难在步骤之间耦合紧, 考虑的极限情况也比较多.