说明:首先这题位于2.7的效率算法,那么要解决它一定是有捷径可走的,只不过可能需要几根头发。
方法:首先我们需要在输入时同步记录当前客栈不同色调客栈出现的次数,即可以在数据输入的同时将所有操作完成。
开三个数组dp1[55],dp2[55],dp3[55],dp1[i]表示咖啡馆最低消费大于p,色调为i的客栈数,dp2[i]咖啡馆最低消费小于等于p,色调为i的客栈数,dp3[i]表示该客栈前,最近出现的咖啡馆最低消费小于等于p,色调为i的客栈前与该客栈色调相同的数量(仔细思考可以发现,如果出现了一个最低消费小于等于p的咖啡馆,不管其客栈什么色调,在该客栈及其后面出现的客栈,都能与前面所有色调匹配的客栈构成一对,而dp3的任务就是记录并更新这些客栈数)。
dp1和dp2的记录比较好操作,dp3稍微有些麻烦,这里给出dp3的思路:每遇到一个咖啡馆最低消费小于等于p的客栈数,就用一个循环将所有色调的之前出现过的客栈数更新至dp3,代码如下,稍加理解就行:
for (j = 0; j <= k-1; j++)
dp3[j] = dp1[j] + dp2[j];
具体操作:若遇到一个咖啡馆最低消费小于等于p的客栈,则方法数(用c表示)+= dp1[x] + dp2[x](x表示与当前客栈相同的色调),dp2[x]++,同时用上述对dp3的操作更新所有色调的dp3的值,而如果遇到咖啡馆最低消费大于p的客栈,则c += dp3[x],dp1[x]++,最后输出c即可。
具体代码如下:
#include <iostream> using namespace std; int dp1[55], dp2[55], dp3[55]; int main() { int i, j, n, k, p, x, y; long long c = 0; cin >> n >> k >> p; for (i = 1; i <= n; i++) { cin >> x >> y; if (y > p) { c += dp3[x]; dp1[x]++; } else { c += dp1[x] + dp2[x]; dp2[x]++; for (j = 0; j <= k-1; j++) dp3[j] = dp1[j] + dp2[j]; } } cout << c; return 0; }
写题时需要推断,更需要相信自己的推断,一步步脚踏实地走下去。