USACO 3.3.2 Shopping Offers解题报告
写在前面:因为之前没写的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; }