UVA 11125 Arrange Some Marbles
2011-12-18 20:56
603 查看
UVA_11125
一开始被这个题目的3000组数据吓到了,但后来真正仔细分析之后,才发现复杂度主要不是取决于这3000组数据,因此3000这个数只是唬人的。
看到题目之后,我们发现放石子可以看成一个阶段一个阶段地去放,每次放一组即可,只不过放的时候有些条件限制,那么我们可不可以分阶段进行dp计数呢?
带着这个疑问我们继续分析题目,发现取石子的过程并没有明确的先后顺序,所以我们不能人为规定一个取的顺序,因此每次取一组石子的这个过程只能用枚举去实现。为了能够枚举所取的石子,我们必然在每个阶段都要得知每类还剩多少石子,这样我们就不妨把剩余的每类石子的数量作为一个状态,但这个状态好像比较麻烦,但没关系,仔细想一下就会发现由于石子数比较少,我们可以把这个状态压缩成一个8进制的数,这样最多有8*8*8*8个状态嘛,很少的。
状态已经初步表示完了,但我们发现有个问题没有解决,我们怎么让取的时候避免和前面一组同颜色或者同数量呢?再把状态细化呗,多加两个整数pc、pn吧,一个记录前面石子的颜色,一个记录前面那组石子的数量,这样就好了嘛。但第一组石子呢?也就是说我们最初的时候把这个pc和pn初始化成什么呢?等等,好像还有一个问题我们也没解决,题目还要求首和尾也不能同颜色同数量呀。
但依然没关系,我们就把这两个问题一起解决。保证首尾不同确实不太好处理,但凡是不好处理的我们就偷懒嘛,怎么偷懒?枚举呗。如果我们指定了首或者尾那一组的状态,问题就都解决了。我们不妨指定尾的状态,颜色记为fc,数量记为fn,把两个整数也压缩进dp的状态吧。这样我们也就自然知道pc和pn一开始应该初始化成fc和fn了,于是只要后面取的过程保证不和pc同颜色,且不和pn同数量,自然就保证了首尾也是不同颜色、不同数量的。
现在似乎没什么太多的问题了,剩下的就是看看复杂度能不能承受了,如果不能我们就得想办法优化dp。总的状态4*3*4*3*8*8*8*8,每个状态最多转移4*3次,一共是7077888,时间是没问题的。
哦对,还有那3000组数据,其实我们刚才算的复杂度是包含了所有的状态的,只要我们一直是保持记忆化搜索的状态的话,数据的组数是没关系的,我们依旧不会重复去算一些状态,只不过增加了查询的次数而已。
空间上为了节省一点,前面4个状态我们用4进制,后面4个状态我们用8进制,把8个数压缩成一个整数。
一开始被这个题目的3000组数据吓到了,但后来真正仔细分析之后,才发现复杂度主要不是取决于这3000组数据,因此3000这个数只是唬人的。
看到题目之后,我们发现放石子可以看成一个阶段一个阶段地去放,每次放一组即可,只不过放的时候有些条件限制,那么我们可不可以分阶段进行dp计数呢?
带着这个疑问我们继续分析题目,发现取石子的过程并没有明确的先后顺序,所以我们不能人为规定一个取的顺序,因此每次取一组石子的这个过程只能用枚举去实现。为了能够枚举所取的石子,我们必然在每个阶段都要得知每类还剩多少石子,这样我们就不妨把剩余的每类石子的数量作为一个状态,但这个状态好像比较麻烦,但没关系,仔细想一下就会发现由于石子数比较少,我们可以把这个状态压缩成一个8进制的数,这样最多有8*8*8*8个状态嘛,很少的。
状态已经初步表示完了,但我们发现有个问题没有解决,我们怎么让取的时候避免和前面一组同颜色或者同数量呢?再把状态细化呗,多加两个整数pc、pn吧,一个记录前面石子的颜色,一个记录前面那组石子的数量,这样就好了嘛。但第一组石子呢?也就是说我们最初的时候把这个pc和pn初始化成什么呢?等等,好像还有一个问题我们也没解决,题目还要求首和尾也不能同颜色同数量呀。
但依然没关系,我们就把这两个问题一起解决。保证首尾不同确实不太好处理,但凡是不好处理的我们就偷懒嘛,怎么偷懒?枚举呗。如果我们指定了首或者尾那一组的状态,问题就都解决了。我们不妨指定尾的状态,颜色记为fc,数量记为fn,把两个整数也压缩进dp的状态吧。这样我们也就自然知道pc和pn一开始应该初始化成fc和fn了,于是只要后面取的过程保证不和pc同颜色,且不和pn同数量,自然就保证了首尾也是不同颜色、不同数量的。
现在似乎没什么太多的问题了,剩下的就是看看复杂度能不能承受了,如果不能我们就得想办法优化dp。总的状态4*3*4*3*8*8*8*8,每个状态最多转移4*3次,一共是7077888,时间是没问题的。
哦对,还有那3000组数据,其实我们刚才算的复杂度是包含了所有的状态的,只要我们一直是保持记忆化搜索的状态的话,数据的组数是没关系的,我们依旧不会重复去算一些状态,只不过增加了查询的次数而已。
空间上为了节省一点,前面4个状态我们用4进制,后面4个状态我们用8进制,把8个数压缩成一个整数。
#include<stdio.h> #include<string.h> #define MAXD 1100000 int f[MAXD], a[5], b[5]; int dp(int state) { int i, j, k, t, st = state, ans = 0, fc, fn, pc, pn; if(f[state] != -1) return f[state]; fc = st % 4, st /= 4; fn = st % 4, st /= 4; pc = st % 4, st /= 4; pn = st % 4, st /= 4; k = 0; for(i = 0; i < 4; i ++) { b[i] = st % 8, st /= 8; k += b[i]; } if(k == 0) { if(pc == fc && pn == fn) return f[state] = 1; else return f[state] = 0; } for(i = 0; i < 4; i ++) { if(i == pc) continue; for(j = 1; j <= 3 && j <= b[i]; j ++) { if(j == pn) continue; b[i] -= j; for(k = 3, t = 0; k >= 0; k --) t = t * 8 + b[k]; t = (((t * 4 + j) * 4 + i) * 4 + fn) * 4 + fc; ans += dp(t); b[i] += j; } } return f[state] = ans; } void solve() { int i, j, k, n, res, t; memset(a, 0, sizeof(a)); scanf("%d", &n); k = 0; for(i = 0; i < n; i ++) { scanf("%d", &a[i]); k += a[i]; } if(!k) { printf("1\n"); return ; } for(i = 3, k = 0; i >= 0; i --) k = k * 8 + a[i]; res = 0; for(i = 0; i < n; i ++) for(j = 1; j <= 3 && j <= a[i]; j ++) { t = (((k * 4 + j) * 4 + i) * 4 + j) * 4 + i; res += dp(t); } printf("%d\n", res); } int main() { int t; memset(f, -1, sizeof(f)); scanf("%d", &t); while(t --) solve(); return 0; }
相关文章推荐
- UVA 11125 Arrange Some Marbles
- UVA 11125 - Arrange Some Marbles (dp)
- uva 11125 - Arrange Some Marbles(记忆化搜索)
- Uva 10090 Marbles 扩展欧几里得 费用最小
- UVa 256 Quirksome Squares (枚举||二次同余)
- How to arrange 10 digits so that the product of the some of them is equal to a number represented by the remaining digits
- UVa Problem 10090 Marbles (弹珠)
- UVa 11481 Arrange the Number(容斥原理)
- UVa Problem Solution: 10090 - Marbles
- uva 10090 Marbles
- UVA 10090 - Marbles 拓展欧几里得
- uva 256 - Quirksome Squares
- uva 11481 Arrange the Numbers
- uva 11481 - Arrange the Numbers(计数问题)
- UVa 10090 - Marbles
- UVa10672 - Marbles on a tree(BFS)
- uva 10090 marbles
- UVA10090 Marbles【扩展欧几里得算法】
- UVA 10090 Marbles(扩展欧几里得)
- UVA 11481 Arrange the Numbers (容斥)