250p:大水题,给你一幅图,水平可以连续染色red,垂直可以连续染色blue,水平垂直都有染色就是green,问从空白图到给你的图最少需要多少次染色。对于red和blue分开考虑就可以了,也可以先把green转换为red或者blue,然后贪心搞。
500p:令人蛋疼的题,弄了一天,往dp上想破了脑子最后居然算法还是错的,最后参考了Soooooooo大神的解题思路才搞出来 http://hi.baidu.com/ryannnnnnnn/item/76af1d161b61b0e964eabf29
题意 :在数轴上有一些球,这里简化为点,他们都以相等的速度或左或右的移动,给你两张图,一张是点原来的位置,另一张是移动后的位置,问有多少种方案使得第一张图的点对应到第二张的图的点,注意第二张图可以加入新的点。
由此,假设第一张图为A,第二张为B,首先对于他们都要排好序。
对于A中的点在B中最多对应两个点,而且A中的两个点如果在B中对应一个点,一定是A[i]+dis = A[j]-dis,首先我们可以计算出所有可能的速度,然后对于每一个速度计算方案数相加即可。
对于A中未访问过的点,向B拓展一条链,比如B1-A1-B2-A2-..-Bk-Ak-B(k+1),
举个例子 假设A中有1 3 5 7 10 B中有2 4 6 9 12
对于速度为1的情况,从A中第一个点开始拓展可以得到
1 3 5 7
2 4 6
这条链就是a[0] - b[0] - a[1] - b[1] - a[2] - b[2] - a[3]
有了的思路,自己心里也就很清楚了,毕竟搞了一天了,印象还是很深刻的。也就是说对于某个速度dis,我们要找到所有的链,而所有的链都是互不相干的,那么所有链的情况数相乘就是这个dis的所有情况数,对于上下点相等的链,只有一种配对方法,对于下面点比上面多一的,有下面点数中配对方法,上面点比下面多一的显然就不可能配对,这几种情况在图上画一下就很清楚了。
#include <vector> #include <list> #include <map> #include <set> #include <deque> #include <stack> #include <bitset> #include <algorithm> #include <functional> #include <numeric> #include <utility> #include <sstream> #include <iostream> #include <iomanip> #include <cstdio> #include <cmath> #include <string.h> #include <cstdlib> #include <ctime> #define LL long long using namespace std; class OneDimensionalBalls { public: LL countValidGuesses(vector <int>, vector <int>); }; int juli[55]; bool vis[55]; LL OneDimensionalBalls::countValidGuesses(vector <int> fp, vector <int> sp) { int i, j; sort(fp.begin(), fp.end()); int num = 0; printf("%d\n", sp.size()); for(i = 0;i < sp.size(); i++) { int dis = abs(sp[i] - fp[0]); if(dis == 0) continue; for(j = 1;j < fp.size(); j++) { int zai = fp[j] - dis; int x = lower_bound(sp.begin(), sp.end(), zai) - sp.begin(); if(x < sp.size() && sp[x] == zai) continue; zai = fp[j] + dis; x = lower_bound(sp.begin(), sp.end(), zai) - sp.begin(); if(x < sp.size() && sp[x] == zai) continue; break; } if(j == fp.size()) juli[num++] = dis ; } LL ans = 0; if(num == 0) return ans; sort(juli, juli+num); int k = 1; for(i = 1;i < num; i++) if(juli[i] != juli[i-1]) juli[k++] = juli[i]; num = k; for(i = 0;i < num; i++) { memset(vis, 0, sizeof(vis)); LL mul = 1; for(j = 0;j < fp.size(); j++) { if(vis[j]) continue; vis[j] = 1; int up = 1; int down = 0; int x = fp[j]-juli[i]; int pos = lower_bound(sp.begin(), sp.end(), x) - sp.begin(); if(pos < sp.size() && sp[pos] == x) down++; int to = j; while(1) { x = fp[to]+juli[i]; pos = lower_bound(sp.begin(), sp.end(), x) - sp.begin(); if(pos < sp.size() && sp[pos] == x) { down++; } else break; x = fp[to]+2*juli[i]; pos = lower_bound(fp.begin(), fp.end(), x) - fp.begin(); if(pos < fp.size() && fp[pos] == x) { up++; vis[pos] = 1; to = pos; } else break; } if(up == down-1) mul = down*mul; else if(up == down+1) mul = 0; } ans += mul; } printf("%lld\n", ans); return ans; }