今天去打酱油的。。。水了四道题,给各种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;
}
C. Robot
广度优先搜索的变种,关键问题在于要优化搜索的步骤,防止超时和超内存空间,比赛的时候一开始就超时超到死。。。
#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;
}
F. Balloon
首先要注意到数据范围很小,因此可以进行暴力搜索,为了提高搜索的效率,可以采用位运算来记录当前气球是否已经被击中,以及采用备忘录式的动态规划也有助于提高算法效率。
#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;
}
H. Chemical Reaction
注意到数据规模较大,而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;
}
好像暴露我是哪所学校的了。。。渣渣啊。。。