今天去打酱油的。。。水了四道题,给各种IOI、ACM Final的大神跪。。。
B. Easy Task
根据给出的条件,不停地更新上界和下届即可,水题。
#include <iostream> #include <stdlib.h> #include <cassert> #include <queue> #include <stack> #include <vector> #include <map> #include <set> #include <string> #include <iomanip> #include <string.h> #include <algorithm> #include <cmath> #include <iomanip> #include <limits.h> #include <utility> using namespace std; int main() { int t; cin>>t; for(int i=1; i<=t; i++) { int n; cin>>n; int upp = INT_MAX-10; int low = INT_MIN+10; int equal = -1; bool flag = false; for(int j=0; j<n; j++){ string s; int cur; cin>>s>>cur; if(s == "=") { flag = true; } else if(s == ">=") { low = max(low, cur); } else if(s == ">") {low = max(low, cur+1); } else if(s == "<=") {upp = min(upp, cur); } else if(s == "<") {upp = min(upp, cur-1);} } if(flag){cout<<1<<endl;} else if(upp==INT_MAX-10 || low==INT_MIN+10){cout<<-1<<endl;} else{cout<<(upp-low+1)<<endl;} } return 0; }
广度优先搜索的变种,关键问题在于要优化搜索的步骤,防止超时和超内存空间,比赛的时候一开始就超时超到死。。。
#include <iostream> #include <stdlib.h> #include <cassert> #include <queue> #include <stack> #include <vector> #include <map> #include <set> #include <string> #include <iomanip> #include <string.h> #include <algorithm> #include <cmath> #include <iomanip> #include <limits.h> #include <utility> using namespace std; const int dir_x[] = {0, 0, -1, 1}; const int dir_y[] = {1, -1, 0, 0}; int main() { int t; cin>>t; while(t--){ int row, col; cin>>row>>col; string g[4005]; int res = 0; for(int i=0; i<row; i++){ cin>>g[i]; } queue<pair<int, int> > A, B; while(A.empty() == false) A.pop(); while(B.empty() == false) B.pop(); char prev = g[0][0]; char cur = g[0][0]; g[0][0] = 'Z'; if(cur == 'A') A.push(make_pair(0, 0)); else B.push(make_pair(0, 0)); while(true){ if(cur == 'A'){ if(A.empty()) break; while(A.empty()==false){ pair<int, int> p = A.front(); A.pop(); int x = p.first; int y = p.second; for(int i=0; i<4; i++){ int xx = x+dir_x[i]; int yy = y+dir_y[i]; if(xx>=row || xx<0 || yy>=col || yy<0) continue; if(g[xx][yy]=='Z' || g[xx][yy]=='.') continue; if(g[xx][yy]=='A'){ g[xx][yy] = 'Z'; A.push(make_pair(xx, yy)); continue; } else if(g[xx][yy]=='B'){ g[xx][yy] = 'Z'; B.push(make_pair(xx, yy)); continue; } } } res++; } else if(cur == 'B'){ if(B.empty()) break; while(B.empty()==false){ pair<int, int> p = B.front(); B.pop(); int x = p.first; int y = p.second; for(int i=0; i<4; i++){ int xx = x+dir_x[i]; int yy = y+dir_y[i]; if(xx>=row || xx<0 || yy>=col || yy<0) continue; if(g[xx][yy]=='Z' || g[xx][yy]=='.') continue; if(g[xx][yy]=='B'){ g[xx][yy] = 'Z'; B.push(make_pair(xx, yy)); continue; } else if(g[xx][yy]=='A'){ g[xx][yy] = 'Z'; A.push(make_pair(xx, yy)); continue; } } } res++; } if(prev == 'A') {cur = 'B'; prev = 'B'; } else if(prev == 'B') {cur = 'A'; prev = 'A';} } cout<<res<<endl; } return 0; }
首先要注意到数据范围很小,因此可以进行暴力搜索,为了提高搜索的效率,可以采用位运算来记录当前气球是否已经被击中,以及采用备忘录式的动态规划也有助于提高算法效率。
#include <iostream> #include <stdlib.h> #include <cassert> #include <queue> #include <stack> #include <vector> #include <map> #include <set> #include <string> #include <iomanip> #include <string.h> #include <algorithm> #include <cmath> #include <iomanip> #include <limits.h> #include <utility> using namespace std; int n, t; int x[15], y[15], z[15]; int score[15][5]; int dp[3000][5]; int res = 0; bool flag = false; bool check(int a1, int b1, int c1, int a2, int b2, int c2){ double lam = 0; if(a2 != 0){ lam = ((double)a1)/a2; } else if(b2 != 0) {lam = ((double)b1)/b2; } else{ lam = ((double)c1)/c2; } if(fabs(a1-lam*a2) > 1e-6) return false; else if(fabs(b1-lam*b2) > 1e-6) return false; else if(fabs(c1-lam*c2) > 1e-6) return false; return true; } bool solve(int cur, int shoot) { if(cur==((1<<n)-1)){ flag = true; return true;} if(shoot>=t) return false; if(dp[cur][shoot]>0) return true; vector<int> v; v.clear(); bool res = false; for(int i=0; i<n; i++){ if(((1<<i)&cur) == 0) v.push_back(i); } int len = v.size(); for(int i=0; i<len; i++){ bool tt = solve(cur|(1<<v[i]), shoot+1); if(tt){ dp[cur][shoot] = max(dp[cur][shoot], dp[cur|(1<<v[i])][shoot+1]+score[v[i]][shoot] ); res = true; } } int tmp = 0; for(int i=0; i<len; i++) for(int j=i+1; j<len; j++){ int st = cur|(1<<v[i]); st = st|(1<<v[j]); tmp = score[v[i]][shoot]+score[v[j]][shoot]; int a1 = x[v[i]]-x[v[j]]; int b1 = y[v[i]]-y[v[j]]; int c1 = z[v[i]]-z[v[j]]; for(int k=0; k<len; k++) { if(k==i || k==j) continue; int a2 = x[v[i]]-x[v[k]]; int b2 = y[v[i]]-y[v[k]]; int c2 = z[v[i]]-z[v[k]]; bool ok = check(a1, b1, c1, a2, b2, c2); if(ok){ st = st|(1<<v[k]); tmp += score[v[k]][shoot]; } } bool tt = solve(st, shoot+1); if(tt){ res = true; dp[cur][shoot] = max(dp[cur][shoot], tmp+dp[st][shoot+1]); } } return res; } int main() { int c; cin>>c; while(c--) { flag = false; cin>>n>>t; for(int i=0; i<n; i++) cin>>x[i]>>y[i]>>z[i]; for(int i=0; i<n; i++) for(int j=0; j<t; j++) cin>>score[i][j]; memset(dp, 0, sizeof(dp)); res = 0; bool ok = solve(0, 0); if(flag && ok) cout<<dp[0][0]<<endl; else cout<<-1<<endl; } return 0; }
注意到数据规模较大,而b属性符号不同的元素不可能产生正能量,所以可考虑将b为正和b为负的两种情形分开来讨论,对于每一种情形,应该找到O(N)的算法,否则就很可能会超时,方法是采用两个指针分别在左右两侧扫描,和two sum问题挺像的。
#include <iostream> #include <stdlib.h> #include <stdio.h> #include <cassert> #include <queue> #include <stack> #include <vector> #include <map> #include <set> #include <string> #include <iomanip> #include <string.h> #include <algorithm> #include <cmath> #include <iomanip> #include <limits.h> #include <utility> using namespace std; int main() { int c; cin>>c; while(c--) { int n; scanf("%d", &n); long long res = -9999999999LL; if(n < 50){ vector<pair<long long, long long> > v; v.clear(); for(int i=0; i<n; i++){ pair<long long, long long> p; cin>>p.first>>p.second; v.push_back(p); } for(int i=0; i<n; i++) for(int j=i+1; j<n; j++){ long long tmp = (v[i].second*v[j].second)/(max(abs(v[i].second), abs(v[j].second))); res = max(res, (long long)abs(v[i].first-v[j].first)*tmp); } cout<<res<<endl; continue; } vector<pair<long long, long long> > pos, neg; pos.clear(); neg.clear(); for(int i=0; i<n; i++){ pair<long long, long long> p; cin>>p.first>>p.second; //scanf("%d%d", &p.first, &p.second); if(p.second < 0) neg.push_back(p); else pos.push_back(p); } sort(pos.begin(), pos.end()); sort(neg.begin(), neg.end()); int len = neg.size(); for(int i=0; i<len; i++) neg[i].second = -neg[i].second; int right = pos.size()-1; int left = 0; int ptr; while(right > left){ res = max(res, (long long)(pos[right].first-pos[left].first)*min(pos[right].second, pos[left].second)); if (pos[right].second < pos[left].second){ ptr = right-1; while(ptr>left && pos[ptr].second<pos[right].second) ptr--; right = ptr; if(right <= left) break; res = max(res, (long long)(pos[right].first-pos[left].first)*min(pos[right].second, pos[left].second)); } else{ ptr = left+1; while(ptr<right && pos[ptr].second<pos[left].second) ptr++; left = ptr; if(right <= left) break; res = max(res, (long long)(pos[right].first-pos[left].first)*min(pos[right].second, pos[left].second)); } } right = neg.size()-1; left = 0; while(right > left){ res = max(res, (long long)(neg[right].first-neg[left].first)*min(neg[right].second, neg[left].second)); if (neg[right].second < neg[left].second){ ptr = right-1; while(ptr>left && neg[ptr].second<neg[right].second) ptr--; right = ptr; if(right <= left) break; res = max(res, (long long)(neg[right].first-neg[left].first)*min(neg[right].second, neg[left].second)); } else{ ptr = left+1; while(ptr<right && neg[ptr].second<neg[left].second) ptr++; left = ptr; if(right <= left) break; res = max(res, (long long)(neg[right].first-neg[left].first)*min(neg[right].second, neg[left].second)); } } cout<<res<<endl; } return 0; }