USACO Shopping Offers 解题报告
2013-04-06 19:29
323 查看
这道题刚开始用搜索做的,即遍历每种特惠的可能次数,最后取最省的组合。虽然用到了剪枝(当当前的费用已经超过了当前最省的组合,就不必接着考虑后面的特惠了),但是仍然效率特别低,在遇到后面的测试点的时候程序就无止境地跑下去了。
后来看到网上说用动态规划,因为最多只有5种商品,每种商品最多买5个,所以状态总数特别少,只有6^5=7776。所以用动态规划把表填了就好。
简单总结:
1.每次做题对状态总数要有个大致的估计,像最近做的这几道题,如果状态空间很小(运算重量级万或运算轻量级十万以下),直接枚举就好(会通过动态规划等方法用到之前的状态)。
2.好的算法和差的算法的运行效率有天壤之别。之前的搜索的方法面对稍大的数据,就永远等不出结果了。而动态规划的方法仍然是blazingly fast.
代码如下:
后来看到网上说用动态规划,因为最多只有5种商品,每种商品最多买5个,所以状态总数特别少,只有6^5=7776。所以用动态规划把表填了就好。
简单总结:
1.每次做题对状态总数要有个大致的估计,像最近做的这几道题,如果状态空间很小(运算重量级万或运算轻量级十万以下),直接枚举就好(会通过动态规划等方法用到之前的状态)。
2.好的算法和差的算法的运行效率有天壤之别。之前的搜索的方法面对稍大的数据,就永远等不出结果了。而动态规划的方法仍然是blazingly fast.
代码如下:
/* ID: thestor1 LANG: C++ TASK: shopping */ #include <iostream> #include <cmath> #include <cstdio> #include <cstring> #include <vector> #include <cassert> #include <string> #include <algorithm> #include <stack> #include <set> #include <queue> #include <map> using namespace std; const int P = 5; const int S = 99; int main() { FILE *fin = fopen ("shopping.in", "r"); FILE *fout = fopen ("shopping.out", "w"); //freopen("log.txt", "w", stdout); int s; fscanf(fin, "%d", &s); map<int, int> cid; int sos[S][6] = {0}; int id = 0; for(int i = 0; i < s; ++i) { int n; fscanf(fin, "%d", &n); for(int j = 0; j < n; ++j) { int c; fscanf(fin, "%d", &c); if(cid.find(c) == cid.end()) { cid[c] = id; id++; } fscanf(fin, "%d", &sos[i][cid[c]]); } fscanf(fin, "%d", &sos[i][5]); } int b; fscanf(fin, "%d", &b); int require[P] = {0}; int price[P] = {0}; for(int i = 0; i < b; ++i) { int c; fscanf(fin, "%d", &c); if(cid.find(c) == cid.end()) { cid[c] = id; id++; } fscanf(fin, "%d", &require[cid[c]]); fscanf(fin, "%d", &price[cid[c]]); } assert(id <= 5); int f[6][6][6][6][6]; int num[5] = {0}; for(num[0] = 0; num[0] <= require[0]; ++num[0]) { for(num[1] = 0; num[1] <= require[1]; ++num[1]) { for(num[2] = 0; num[2] <= require[2]; ++num[2]) { for(num[3] = 0; num[3] <= require[3]; ++num[3]) { for(num[4] = 0; num[4] <= require[4]; ++num[4]) { if(!num[0] && !num[1] && !num[2] && !num[3] && !num[4]) { f[0][0][0][0][0] = 0; continue; } f[num[0]][num[1]][num[2]][num[3]][num[4]] = -1; for(int i = 0; i < 5; ++i) { int nnum[5]; for(int j = 0; j < 5; ++j) { nnum[j] = num[j]; } if(num[i] > 0) { nnum[i] = num[i] - 1; if(f[num[0]][num[1]][num[2]][num[3]][num[4]] < 0 || f[nnum[0]][nnum[1]][nnum[2]][nnum[3]][nnum[4]] + price[i] < f[num[0]][num[1]][num[2]][num[3]][num[4]]) { f[num[0]][num[1]][num[2]][num[3]][num[4]] = f[nnum[0]][nnum[1]][nnum[2]][nnum[3]][nnum[4]] + price[i]; } } } for(int i = 0; i < s; ++i) { bool possible = true; for(int j = 0; j < 5; ++j) { if(sos[i][j] > num[j]) { possible = false; break; } } if(!possible) { continue; } int nnum[5]; for(int j = 0; j < 5; ++j) { nnum[j] = num[j] - sos[i][j]; } assert(f[num[0]][num[1]][num[2]][num[3]][num[4]] > 0); if(f[nnum[0]][nnum[1]][nnum[2]][nnum[3]][nnum[4]] + sos[i][5] < f[num[0]][num[1]][num[2]][num[3]][num[4]]) { f[num[0]][num[1]][num[2]][num[3]][num[4]] = f[nnum[0]][nnum[1]][nnum[2]][nnum[3]][nnum[4]] + sos[i][5]; } } } } } } } fprintf(fout, "%d\n", f[require[0]][require[1]][require[2]][require[3]][require[4]]); return 0; }
相关文章推荐
- poj 1170-Shopping Offers解题报告
- USACO :Longest Prefix解题报告
- USACO历年比赛题目列表,测试数据和解题报告下载
- USACO Riding the Fences 解题报告
- USACO:Bessie Come Home解题报告
- USACO Section1.3 Combination Lock 解题报告
- USACO Section1.5 Number Triangles 解题报告
- USACO 5.3解题报告
- USACO 2.3.2 Cow Pedigrees 解题报告
- USACO 1.1 Your ride is here 解题报告
- 解题报告 物理(即 usaco 5.1.2)
- USACO Section2.3 Money Systems 解题报告 【icedream61】
- USACO Combination Lock 解题报告
- USACO Milk Measuring 解题报告
- USACO Fence Loops 解题报告
- USACO Betsy's Tour 解题报告
- usaco 3.3 Shopping Offers
- USACO :Cow Pedigrees解题报告
- Usaco 4.3.1 Buy Low, Buy Lower 逢低吸纳详细解题报告
- USACO 2016 open Silver 解题报告