写在前面:因为之前没写的C++的USACO Training的解题报告太多……所以就不写了,要是想要代码可以联系我:xiedong_1993@foxmail.com
这题就是传说中的五维背包,其实写起来难度不大。但是我写的时候可以说是遇到了重重困难。因为我对C++的掌握还不如Pascal,所以很多东西写的不是很熟。这题有一个很大的问题就在于,最后有用的只有五种物品,但是物品的编号却又很多。处理的方法有几种,一种是离散化,但是这个太SB了。。为了处理这么弱的数据还要排序重标号实在得不偿失。另一种是直接就标号,但是面临的问题就是,需要用的五种标号在能标之前就要被用到,就涉及到了一个问题,如何略过前面的部分,先处理后面的。。
两种方案:1、全读到一个数组里面,然后再将这个数组重新处理。这个方法可以是可以,但是浪费时间也浪费空间。
2、先直接不读前面的部分,读后面的,然后关文件,再开一遍,把前面的读进来。我这里用的就是后者。
我们知道pascal处理这个问题很简答,只要reset一下就好。但是C++需要先关闭文件,再全部重新关联一遍。因此学会了fclose……fclose之后重新freopen就好了。
还有更悲剧的,pascal中跳过一样直接readln就好,但是C++貌似读个回车是不好使的。。。还得挨个字符跳,不知有没有好的其他的方法……
我的方法:
for (int i = 0; i < m; i++)
{char ch = '\0';while (ch != '\n') scanf("%c", &ch);
}
这两个问题处理了之后依旧卡了很长时间,很简单……遇到一个USACO的exit code,我最开始觉得可能是那块的库他没有,但是后来发现是超内存了。。。(注意:以后如果在USACO遇到exit code 127就是超内存了)剩下的DP就简单了,dp[i1][i2][i3][i4][i5]就是五样东西各这些个的时候需要的最少花费。
代码:
/*
TASK:shopping
LANG:C++
*/
#include <iostream>
#include <fstream>
#include <climits>
using namespace std;int n,m;
int no[1200], cost[120];
int need[6];
int data[120][6];
int dp[14][14][14][14][14];
const int inf = INT_MAX;void init()
{scanf("%d\n", &m);for (int i = 0; i < m; i++){char ch = '\0';while (ch != '\n') scanf("%c", &ch);}scanf("%d", &n);for (int i = 0; i < 120; i++) no[i] = -1;for (int i = 0; i < n; i++){int x,y,w;scanf("%d%d%d", &x, &y, &w);no[x] = i; need[i] = y;cost[m + i] = w; data[m + i][i] = 1;}fclose(stdin);freopen("shopping.in", "r", stdin);scanf("%d", &m);for (int i = 0; i < m; i++){int num;scanf("%d", &num);for (int j = 0; j < num; j++){int x,y;scanf("%d%d", &x, &y);if (no[x] != -1)data[i][no[x]] += y;}scanf("%d", &cost[i]);}m += n;for (int i1 = 0; i1 <= need[0]; i1++)for (int i2 = 0; i2 <= need[1]; i2++)for (int i3 = 0; i3 <= need[2]; i3++)for (int i4 = 0; i4 <= need[3]; i4++)for (int i5 = 0; i5 <= need[4]; i5++)dp[i1][i2][i3][i4][i5] = inf;
}void solve()
{dp[0][0][0][0][0] = 0;for (int i1 = 0; i1 <= need[0]; i1++)for (int i2 = 0; i2 <= need[1]; i2++)for (int i3 = 0; i3 <= need[2]; i3++)for (int i4 = 0; i4 <= need[3]; i4++)for (int i5 = 0; i5 <= need[4]; i5++)if (dp[i1][i2][i3][i4][i5] < inf)for (int i = 0; i < m; i++){int t1 = i1 + data[i][0];int t2 = i2 + data[i][1];int t3 = i3 + data[i][2];int t4 = i4 + data[i][3];int t5 = i5 + data[i][4];dp[t1][t2][t3][t4][t5] = min(dp[t1][t2][t3][t4][t5], dp[i1][i2][i3][i4][i5] + cost[i]);}
}void print()
{printf("%d\n", dp[need[0]][need[1]][need[2]][need[3]][need[4]]);
}int main()
{freopen("shopping.in", "r", stdin);freopen("shopping.out", "w", stdout);init();solve();print();return 0;
}