算法思考过程:
1.goose周围一定距离内必定是goose,根据这个条件,整个图可以分成很多独立的区域。
2.每个区域内可以是goose或duck,互不影响。但是根据题目要求,须保证至少有一个区域是goose。
3.找出区域数n,最后可能的情况是(2^n-1)%1000000007。
4.时间复杂度:算法实现出来用了4重循环,时间复杂度为O(n^4)。但是这四重循环内的操作主要是为了去标志set,而set的大小为n^2,且每个元素只被标记一次,即实际的时间复杂度应该是O(n^2)。
菜鸟改了好几次后的代码:
import java.util.*; import java.util.regex.*; import java.text.*; import java.math.*; public class GooseInZooDivTwo { private int lenx,leny; public int count(String[] field, int dist) { boolean[][] set = new boolean[50][50]; int i,j,count; lenx=field.length; leny=field[0].length(); count=0; for(i=0;i<lenx;i++){ for(j=0;j<leny;j++){ if(field[i].charAt(j)=='v'&&!set[i][j]){ update(set,i,j,field,dist); count++; } } } int r=1; for(i=0;i<count;i++){ r=(r*2)%1000000007; } return r-1; } private void update(boolean[][] set,int point_x,int point_y,String[] field,int dist){ int i,j; set[point_x][point_y]=true; for(i=0;i<lenx;i++){ for(j=0;j<leny;j++){ if(field[i].charAt(j)=='v'&&Math.abs(i-point_x)+Math.abs(j-point_y)<=dist&&!set[i][j]){ update(set,i,j,field,dist); } } } } } //Powered by KawigiEdit 2.1.4 (beta) modified by pivanof!
大神的代码(Java):
import java.util.*; public class GooseInZooDivTwo { boolean visited[][] = new boolean[51][51]; public int count(String[] field, int dist) { int res = 0; int mod = 1000000007; int N = field.length; int M = field[0].length(); int block = 0; for (int i = 0; i < N; i++) for (int j = 0; j < M; j++) if (field[i].charAt(j) == 'v' && !visited[i][j]) { fill(i, j, field, dist); block++; } //System.out.println(block); if (block > 0) { res = 1; for (int i = 0; i < block; i++) { res = (res*2)%mod; } res --; } return res; } private void fill(int i, int j, String[] field, int dist) { int N = field.length; int M = field[0].length(); visited[i][j] = true; for (int x = 0; x < N; x++) for (int y = 0; y < M; y++) if (Math.abs(x-i) + Math.abs(y-j) <= dist && field[x].charAt(y) == 'v' && !visited[x][y]) { fill(x, y, field, dist); } } } // Powered by FileEdit // Powered by CodeProcessor
大神的代码(C++):
#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 <cstdlib> #include <ctime> using namespace std; #define ALL(v) (v).begin(),(v).end() #define RALL(v) (v).rbegin(),(v).rend() #define UNIQ(v) sort(ALL(v)),v.erase(unique(ALL(v)),(v).end()) typedef long long ll; typedef long double ld; class GooseInZooDivTwo { public: int count(vector <string>, int); }; vector< pair<int, int> > bds; vector<bool> used; int dist; void dfs(int v) { used[v] = 1; for (size_t i = 0; i < bds.size(); ++i) { if (!used[i] && abs(bds[v].first-bds[i].first) + abs(bds[v].second-bds[i].second) <= dist) dfs(i); } } int GooseInZooDivTwo::count(vector <string> field, int _dist) { dist = _dist; for (size_t i = 0; i < field.size(); ++i) for (size_t j = 0; j < field[0].size(); ++j) if (field[i][j] == 'v') bds.push_back(make_pair(i,j)); int n = bds.size(); used.resize(n, 0); long long d = 0; for (int i = 0; i < n; ++i) if (!used[i]) { ++d; dfs(i); } if (!d) return 0; long long ans = 1; for (int i = 0; i < d; ++i) ans = (ans*2) % 1000000007; ans = (ans-1+1000000007) % 1000000007; return (int)ans; } //Powered by [KawigiEdit] 2.0!
分析:
算法:Greedy, Simple Math
对比:
1.C++大神考虑得更全面。ans=(ans-1+1000000007)%1000000007;虽然2^n不可能达到1000000008的倍数。
2.C++大神的vector<pair<int,int>>用得出神入化啊,菜鸟表示学习了。
3.我和java大神基本上一样的。
问题:这道题贪心使用在哪里?