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;
}