RC-u1 大家一起查作弊
字符串持续读入,while(getlinre(cin,s))后按空格分割字符串即可。
#include<bits/stdc++.h>
using namespace std;
int judge(char c)
{
if(c>='a'&&c<='z') return 1;
if(c>='A'&&c<='Z') return 1;
if(c>='0'&&c<='9') return 1;
return 0;
}
int main()
{
string s;
vector<string>v;
int cnt=0;
while(getline(cin,s))
{
int n=s.length();
s+='?';
string str="";
for(int i=0;i<n;i++)
{
for(int j=i;j<=n;j++)
{
if(!judge(s[j]))
{
if(str.length()) v.push_back(str);
str="";
i=j;
break;
}
str+=s[j];
}
}
}
int x=0,y=0;
for(auto str:v)
{
int n=str.length();
int f1=0,f2=0,f3=0;
for(int i=0;i<n;i++)
{
char c=str[i];
if(c>='a'&&c<='z') f1=1;
if(c>='A'&&c<='Z') f2=1;
if(c>='0'&&c<='9') f3=1;
}
if(f1&&f2&&f3) x+=5;
else if((f2&&f3)||(f1&&f3)) x+=3;
else if(f1&&f2) x++;
y+=n;
}
cout<<x<<endl<<y<<" "<<v.size();
}
RC-u2 谁进线下了?II
模拟,为了减少代码量可以发现后面十几名的分数都是有规律的:分数与名次之和为20.
#include<bits/stdc++.h>
using namespace std;
struct node{
int x,idx,flag;
}a[35];
bool cmp(node A,node B)
{
if(A.x==B.x) return A.idx<B.idx;
return A.x>B.x;
}
int f(int x)
{
if(x==1) return 25;
else if(x==2) return 21;
else if(x==3) return 18;
else return 20-x;
}
int main()
{
int t;
cin>>t;
for(int i=1;i<=30;i++) a[i].idx=i,a[i].flag=0;
while(t--)
{
for(int i=1;i<=20;i++)
{
int num,y;
cin>>num>>y;
a[num].x+=f(y);
a[num].flag=1;
}
}
sort(a+1,a+31,cmp);
for(int i=1;i<=30;i++)
if(a[i].flag) cout<<a[i].idx<<" "<<a[i].x<<endl;
}
RC-u3 势均力敌
dfs,第一次枚举排列,第二次枚举其中一个集合的元素。
据说是有规律的,n的范围可以扩大到1000.
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int n,a[10],st[10],st2[100010],flag=0,sum=1;
vector<ll>v;
vector<ll>x,y;
void dfs(int u,int x)
{
if(u>=n)
{
v.push_back(x);
return;
}
for(int i=0;i<n;i++)
{
if(st[i]) continue;
st[i]=1;
dfs(u+1,x*10+a[i]);
st[i]=0;
}
}
void dfs2(int u)
{
if(flag||u==v.size()) return;
if(x.size()==sum/2)
{
ll s1=0,s2=0;
for(int i=0;i<v.size();i++)
if(!st2[i]) s2+=v[i]*v[i];
for(auto i:x) s1+=i*i;
if(s1==s2)
{
for(auto i:x) cout<<i<<endl;
flag=1;
}
return;
}
x.push_back(v[u]);
st2[u]=1;
dfs2(u+1);
st2[u]=0;
x.pop_back();
dfs2(u+1);
}
int main()
{
memset(st,0,sizeof(st));
memset(st2,0,sizeof(st2));
cin>>n;
for(int i=1;i<=n;i++) sum*=i;
for(int i=0;i<n;i++) cin>>a[i];
dfs(0,0);
dfs2(0);
}
RC-u4 City 不 City
两种代价的dijkstra,增加一个属性后在优先队列中分别维护即可。注意一个是路径加和,另一个是点权最值。
#include<bits/stdc++.h>
using namespace std;
int n,m,s,T,a[1010],st[1010],h[1010],e[10010],ne[10010],w[10010],d1[1010],d2[1010],idx=0;
struct Node{
int node,x,y;//x路径花费,y节点花费
friend bool operator<(Node A,Node B)
{
if(A.x==B.x) return A.y>B.y;
return A.x>B.x;
}
};
void add(int a,int b,int c)
{
e[idx]=b;
ne[idx]=h[a];
w[idx]=c;
h[a]=idx++;
}
void dijkstra()
{
priority_queue<Node>q;
q.push({s,0,0});
d1[s]=0,d2[s]=0;
while(q.size())
{
Node t=q.top();
q.pop();
int u=t.node,x=t.x,y=t.y;
if(st[u]) continue;
st[u]=1;
for(int i=h[u];i!=-1;i=ne[i])
{
int j=e[i];
if(d1[j]>d1[u]+w[i])
{
d1[j]=d1[u]+w[i];
if(T!=j) d2[j]=max(d2[u],a[j]);
else d2[j]=d2[u];
q.push({j,d1[j],max(d2[u],a[j])});
}
else if(d1[j]==d1[u]+w[i])
{
if(d2[j]>max(d2[u],a[j]))
{
if(T!=j) d2[j]=max(d2[u],a[j]);
else d2[j]=d2[u];
q.push({j,d1[j],max(d2[u],a[j])});
}
}
}
}
}
int main()
{
memset(h,-1,sizeof(h));
memset(st,0,sizeof(st));
memset(d1,0x3f,sizeof(d1));
memset(d2,-0x3f,sizeof(d2));
cin>>n>>m>>s>>T;
for(int i=1;i<=n;i++) cin>>a[i];
while(m--)
{
int x,y,z;
cin>>x>>y>>z;
add(x,y,z),add(y,x,z);
}
dijkstra();
if(d1[T]>1e9) cout<<"Impossible";
else cout<<d1[T]<<" "<<d2[T];
}
RC-u5 贪心消消乐(WA一个点)
直接暴力模拟,开一个无限循环每次暴力判断是否可以存在消掉的区域,没有了就break。为了降低时间复杂度,开两个二维前缀和数组s和f分别用于快速查询区间和以及区间黑洞的数量,每模拟一次就再更新一遍这两个数组。这个做法不会超时,但是有个点错了不知道为什么。还有注意这里的横纵坐标和我们常用的是相反的。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll n,a[210][210],st[210][210],s[210][210],f[210][210];
int main()
{
memset(a,0,sizeof(a));
memset(st,0,sizeof(st));
memset(s,0,sizeof(s));
memset(f,0,sizeof(f));
cin>>n;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++) cin>>a[i][j];
s[0][0]=0,f[0][0]=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++) s[i][j]=s[i-1][j]+s[i][j-1]-s[i-1][j-1]+a[i][j];
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(a[i][j]==0) f[i][j]=f[i-1][j]+f[i][j-1]-f[i-1][j-1]+1;
else f[i][j]=f[i-1][j]+f[i][j-1]-f[i-1][j-1];
ll ans=0;
while(1)
{
int flag=0,x1=1e9,x2=1e9,y1=1e9,y2=1e9;
ll maxx=0;
for(int j=1;j<=n;j++)
{
for(int i=1;i<=n;i++)
{
for(int l=j;l<=n;l++)
{
for(int k=i;k<=n;k++)
{
int sum=s[k][l]-s[i-1][l]-s[k][j-1]+s[i-1][j-1];
int F=f[k][l]-f[i-1][l]-f[k][j-1]+f[i-1][j-1];
if(F>0) break;
if(sum>maxx) x1=i,y1=j,x2=k,y2=l,maxx=sum,flag=1;
}
}
}
}
ans+=maxx;
if(!flag) break;
int h=x2-x1+1;
for(int i=1;i<x1;i++)
for(int j=y1;j<=y2;j++) a[i+h][j]=a[i][j],a[i][j]=0;
for(int i=x1;i<=x2-x1+1;i++)
for(int j=y1;j<=y2;j++) a[i][j]=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++) s[i][j]=s[i-1][j]+s[i][j-1]-s[i-1][j-1]+a[i][j];
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(a[i][j]==0) f[i][j]=f[i-1][j]+f[i][j-1]-f[i-1][j-1]+1;
else f[i][j]=f[i-1][j]+f[i][j-1]-f[i-1][j-1];
cout<<"("<<y1<<", "<<x1<<") ("<<y2<<", "<<x2<<") "<<maxx<<'\n';
}
cout<<ans;
}
总结:全是模拟,比cf那种数学加思维简单多了,只要基础扎实拿个100+分不是问题