写在前
这周是摆烂的一周。。。
题目总结
P1332 血色先锋队 直接从瘟疫源头广搜,如果点没搜过就标记一下进队,如果搜过并且瘟疫到此点的时间大于这次到此点的时间进队。
#include <bits/stdc++.h>
#define eps 1e-15
using namespace std;
int a[505][505],visit[505][505],nx[4]={-1,1,0,0},ny[4]={0,0,-1,1};
int main()
{
int n,m,n1,n2,t1,t2;
queue<pair<int,int>> qans,q;
pair<int,int> t;
cin>>n>>m>>n1>>n2;
for(int i=1; i<=n1; i++){
cin>>t1>>t2;
t=make_pair(t1,t2);
q.push(t);
visit[t1][t2]=1;
}
for(int i=1; i<=n2; i++){
cin>>t1>>t2;
t=make_pair(t1,t2);
qans.push(t);
}
while(!q.empty()){
t=q.front();
q.pop();
t1=t.first;t2=t.second;
for(int k=0; k<4; k++){
int xx = t1+nx[k],yy = t2+ny[k];
if(xx>=1&&xx<=n&&yy>=1&&yy<=m){
if(visit[xx][yy] == 0)a[xx][yy]=a[t1][t2]+1,t=make_pair(xx,yy),q.push(t),visit[xx][yy]=1;
else if(visit[xx][yy] == 1 && a[xx][yy] > a[t1][t2]+1)a[xx][yy]=a[t1][t2]+1,t=make_pair(xx,yy),q.push(t);
}
}
}
for(int i=1; i<=n2; i++){
t=qans.front();
qans.pop();
cout<<a[t.first][t.second]<<endl;
}
return 0;
}
CF510B Fox And Two Dots 一开始想的是搜索每个点,最终看能否搜回开始的点,时间复杂度较高。 每次深搜标记下当前的坐标,在后续如果能搜回当前点就说明能形成一个圈。
#include <bits/stdc++.h>
#define eps 1e-15
using namespace std;
int nx[4]={-1,1,0,0},ny[4]={0,0,-1,1},visit[55][55],f,n,m;
char a[55][55];
void dfs(int x,int y,int x1,int y1){
if(visit[x1][y1]){
f=1;
return;
}
visit[x1][y1]=1;
for(int k=0; k<4; k++){
int xx=x1+nx[k],yy=y1+ny[k];
if(xx==x&&yy==y)continue;
if(xx>=1&&xx<=n&&yy>=1&&yy<=m&&a[x][y]==a[xx][yy])dfs(x1,y1,xx,yy);
}
}
int main()
{
cin>>n>>m;
for(int i=1; i<=n; i++)
for(int j=1; j<=m; j++)
cin>>a[i][j];
for(int i=1; i<=n; i++)
for(int j=1; j<=m; j++)
{ if(!visit[i][j])dfs(i,j,i,j);
if(f==1){cout<<"Yes";return 0;}
}
cout<<"No";
return 0;
}
P1665 正方形计数 直接爆搜o(n^4),数据最大500,超时。。。
#include <bits/stdc++.h>
#define eps 1e-8
#define PI 3.1415926
using namespace std;
int n,ans;
pair<double,double> p[505],x[4];
double getdis(pair<double,double> p1,pair<double,double> p2){
return sqrt(pow(p1.first-p2.first,2)+pow(p1.second-p2.second,2));
}
bool judge(pair<double,double> p1,pair<double,double> p2,pair<double,double> p3,pair<double,double> p4){
double l[6],a,b;
l[0]=getdis(p1,p2);
l[1]=getdis(p1,p3);
l[2]=getdis(p1,p4);
l[3]=getdis(p2,p3);
l[4]=getdis(p2,p4);
l[5]=getdis(p3,p4);
a=l[0];
for(int i=1; i<6; i++){
if(l[i]==a)continue;
else {b=l[i];break;}
}
for(int i=0; i<6; i++)
if(l[i]!=a && l[i]!=b )return false;
return true;
}
bool dfs(int i,int s){
if(i==4){
bool f=judge(x[0],x[1],x[2],x[3]);
if(f)ans++;
return f;
}
for(int j=s; j<=n; j++){
x[i]=p[j];
if(dfs(i+1,j+1) && i==3)break;
}
return false;
}
int main()
{
cin>>n;
for(int i=1; i<=n; i++)cin>>p[i].first>>p[i].second;
dfs(0,1);
cout<<ans;
return 0;
}
正确的思路应该是枚举每两个点作为对角点,根据对角线算出另外两个点,看是否存在。o(n^3),可以用数组或map降到o(n ^2)
#include <bits/stdc++.h>
#define eps 1e-8
#define PI 3.1415926
using namespace std;
int n,ans;
pair<double,double> p[505];
bool judge(pair<double,double> p1,pair<double,double> p2){
double midx = (p1.first + p2.first) / 2;
double midy = (p1.second + p2.second) / 2;
double x1 = midx - (p1.second - midy), y1 = midy - (midx - p1.first);
double x2 = midx + (p1.second - midy), y2 = midy + (midx - p1.first);
int num=0;
for(int i=1; i<=n; i++){
if((p[i].first==x1&&p[i].second==y1) || (p[i].first==x2&&p[i].second==y2))num++;
}
if(num==2)return true;
else return false;
}
int main()
{
cin>>n;
for(int i=1; i<=n; i++)cin>>p[i].first>>p[i].second;
for(int i=1; i<=n; i++)
for(int j=i+1; j<=n; j++)
if(judge(p[i],p[j])){ans++;
}
cout<<ans/2;
return 0;
}
D. Colorful Stamp 对这种类型的题理解的比较慢,以后需要加强一下。 只需要在每次遇到W时看一下前面R和B的数量,只要都不为0即可。
#include <bits/stdc++.h>
#define eps 1e-15
using namespace std;
string a;
bool check(int i,int j){
int numr=0,numb=0;
for(;i<=j; i++){
if(a[i]=='R')numr++;
else if(a[i]=='B')numb++;
}
return numr&&numb;
}
void solve(){
int n;
bool f=true;
cin>>n;cin>>a;
int i,j;
for(i=0; i<a.length(); i++){
if(a[i]=='W')continue;
j=i+1;
while(j<a.length()&&a[j]!='W')j++;
if(!check(i,j)){
f=false;
break;
};
i=j;
}
if(f)cout<<"YES\n";
else cout<<"NO\n";
}
int main()
{
int t;
cin>>t;
while(t--)solve();
return 0;
}
H. Maximal AND 简单的贪心,记录一下位运算的使用。 dalao博客 dalao博客
位操作符 | 介绍 |
---|
& | 按位与,操作数此位全为1结果为1,否则为0 | | | 按位或,操作数此位有一个1结果为1,没有1为0 | ^ | 按位异或,操作数此位不相同为1,相同为0 | << | 按位左移,高位舍去,低位补零 | >> | 按位右移,高位补零,低位舍去 | ~ | 按位取反,与原来此位相反 | 对于&运算可以用来判断第i位是0是1,例如: | | a&(1<<i),将1左移i位,如果结果是原数,则是1。这个用法也可以用来判断是奇数还是偶数,例如a&1,如果是原数,则是奇数。 | | 对于 | 运算可以用来为2进制数特定的位赋值 | 例如00000 | 00001变成00001,用代码就是0 | <<左移1位相当于数据*2,>>右移1位相当于数据/2 | |
#include <bits/stdc++.h>
#define eps 1e-15
using namespace std;
int n,k,a[35],p[35],ans;
void solve(){
for(int i=30; i>=0; i--){
if(a[i]+k>=n)k-=n-a[i],ans+=p[i];
}
}
int main()
{
int t;cin>>t;
for(int i=0; i<=30; i++)
p[i]=pow(2,i);
while(t--){
int tt;
cin>>n>>k;
memset(a,0,sizeof(a));
ans=0;
for(int i=1; i<=n; i++){
cin>>tt;
for(int j=30; j>=0; j--)if(tt-p[j]>=0)a[j]++,tt-=p[j];
}
solve();
cout<<ans<<endl;
}
return 0;
}
|