目录
A.夺宝奇兵
两两之间的距离就两种情况,取一下最小值即可。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N=1e5+7;
struct Node{
ll x,y;
}a[2][N];
int main()
{
ll n,m;
scanf("%lld%lld",&n,&m);
for(ll i=1;i<=n;i++){
for(ll j=0;j<=1;j++){
scanf("%lld%lld",&a[j][i].x,&a[j][i].y);
}
}
ll ans=0;
for(ll i=1;i<n;i++){
ll la=abs(a[0][i].x-a[0][i+1].x)+abs(a[0][i].y-a[0][i+1].y)+abs(a[1][i].x-a[1][i+1].x)+abs(a[1][i].y-a[1][i+1].y);
ll lb=abs(a[1][i].x-a[0][i+1].x)+abs(a[1][i].y-a[0][i+1].y)+abs(a[0][i].x-a[1][i+1].x)+abs(a[0][i].y-a[1][i+1].y);
ans+=min(la,lb);
}
ans+=abs(a[0][n].x-a[1][n].x)+abs(a[0][n].y-a[1][n].y);
printf("%lld\n",ans);
return 0;
}
C.最小边覆盖
存在长度大于等于3的链即不合法。然后搜....搜一下也过了。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+7;
const int M=3e5+7;
struct Edge{
int v,nxt;
Edge(int v=0,int nxt=0):v(v),nxt(nxt){}
}e[N*2];
int p[N],edn;
void add(int u,int v){
e[++edn]=Edge(v,p[u]);p[u]=edn;
e[++edn]=Edge(u,p[v]);p[v]=edn;
}
int n,m;
struct Node{
int id,fa,stp;
Node(int id,int fa,int stp):id(id),fa(fa),stp(stp){}
};
bool vis[N];
int d[N];
bool dfs(int u,int f,int stp){
vis[u]=true;
if(stp==3) return 0;
for(int i=p[u];~i;i=e[i].nxt){
int v=e[i].v;
if(v==f) continue;
if(!dfs(v,u,stp+1)) return false;
}
return true;
}
int main()
{
memset(p,-1,sizeof(p));edn=-1;
scanf("%d%d",&n,&m);
int u,v;
for(int i=1;i<=m;i++){
scanf("%d%d",&u,&v);
d[u]++;d[v]++;
add(u,v);
}
bool flag=false;
for(int i=1;i<=n;i++){
if(d[i]==1){
flag=true;
if(dfs(i,-1,0)) continue;
printf("No\n");
return 0;
}
}
if(!flag) printf("No\n");
else printf("Yes\n");
return 0;
}
D.欧拉回路
留坑
F.小小马
马走日,所以每走一步的颜色肯定不一样,也就是说终点和起点的颜色肯定要不一样。然后就是马能不能走到的问题了,棋盘足够大肯定都能走到,棋盘小就搜一下就行了。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N=2e3+7;
int sx,sy,ex,ey;
struct Node{
int x,y,stp;
Node(int x,int y,int stp):x(x),y(y),stp(stp){}
};
int n,m;
int dir[8][2]={2,1,2,-1,-2,1,-2,-1,1,2,1,-2,-1,2,-1,-2};
bool vis[N][N];
bool bfs(){
queue<Node>q;
q.push(Node(sx,sy,0));
while(!q.empty()){
Node t=q.front();q.pop();
vis[t.x][t.y]=true;
for(int k=0;k<8;k++){
int dx=t.x+dir[k][0];
int dy=t.y+dir[k][1];
if(dx<1||dx>n||dy<1||dy>m) continue;
if(vis[dx][dy]) continue;
if((dx==ex)&&(dy==ey)&&(t.stp%2==0)) return true;
q.push(Node(dx,dy,t.stp+1));
}
}
return false;
}
int main()
{
scanf("%d%d",&n,&m);
scanf("%d%d%d%d",&sx,&sy,&ex,&ey);
if(((sx%2)==(sy%2))==((ex%2)==(ey%2))){
printf("No\n");
return 0;
}
if(n>=100&&m>=100){
printf("Yes\n");
return 0;
}
if(bfs()) printf("Yes\n");
else printf("No\n");
return 0;
}
G.置置置换
表示第
位放数字
的情况,
是
数组的前缀和,即:
要考虑到,第位放任何一个数字,前面都是
个数字的排列关系,所以
是可以通过
来转移的,剩下唯一要考虑的是要不要-1,想清楚的话就过了。
答案据说可以三分,然后可以过div1.
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
const ll N=2e3+7;
ll dp[N][N];
ll sum[N][N];
int main()
{
ll n;
scanf("%lld",&n);
dp[1][1]=1;
for(ll i=1;i<=n;i++) sum[1][i]=1;
for(ll i=2;i<=n;i++){
for(ll j=1;j<=i;j++){
if(i%2==0) dp[i][j]=(sum[i-1][i-1]-sum[i-1][j-1]+mod)%mod;
else dp[i][j]=sum[i-1][j-1];
sum[i][j]=(sum[i][j-1]+dp[i][j])%mod;
}
}
printf("%lld\n",sum[n][n]);
return 0;
}
I.咆咆咆哮
首先肯定先放怪,再加攻。枚举放几张怪,每张卡对于这种情况的贡献也就可以算出来,然后贪心的枚举,取最大值即可。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N=2e3+7;
struct Node{
ll a,b,val;
bool operator<(const Node t){
return val>t.val;
}
}ar[N];
int main()
{
ll n;
scanf("%lld",&n);
for(ll i=1;i<=n;i++){
scanf("%lld%lld",&ar[i].a,&ar[i].b);
}
ll ans=0;
for(ll k=1;k<=n;k++){
for(ll i=1;i<=n;i++){
ar[i].val=ar[i].a-ar[i].b*k;
}
sort(ar+1,ar+1+n);
ll tmp=0;
for(ll i=1;i<=k;i++) tmp+=ar[i].a;
for(ll i=k+1;i<=n;i++) tmp+=k*ar[i].b;
ans=max(ans,tmp);
}
printf("%lld\n",ans);
return 0;
}
K.两条路径
对于询问的每个点u,找出四条最大的、以u为端点的、互不相交的链就是答案。对与u相连的所有点做树形dp即可,剩下的就是注意一下输入输出。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N=2e5+7;
ll dp[N],a[N];
struct Edge{
ll v,nxt;
}e[N*2];
ll p[N],edn;
void add(ll u,ll v){
e[++edn]=(Edge){v,p[u]};p[u]=edn;
e[++edn]=(Edge){u,p[v]};p[v]=edn;
}
ll val[N];
ll dfs(ll u,ll f){
ll res=0;
for(ll i=p[u];~i;i=e[i].nxt){
ll v=e[i].v;
if(v==f) continue;
res=max(dfs(v,u),res);
}
return res+a[u];
}
ll qpow(ll a,ll b){
ll res=1;
while(b){
if(b&1) res*=a;
a*=a;b>>=1;
}
return res;
}
ll pri[N];
int main()
{
ll n;
scanf("%lld",&n);
memset(p,-1,sizeof(p));edn=-1;
for(ll i=1;i<=n;i++){
scanf("%lld",&a[i]);
if(a[i]>0) a[i]=qpow(2,a[i]-1);
else if(a[i]<0) a[i]=-qpow(2,-a[i]-1);
}
ll u,v;
for(ll i=1;i<n;i++){
scanf("%lld%lld",&u,&v);
add(u,v);
}
ll q;
scanf("%lld",&q);
while(q--){
scanf("%lld",&u);
ll tot=0;
for(ll i=p[u];~i;i=e[i].nxt){
ll v=e[i].v;
val[++tot]=dfs(v,u);
}
sort(val+1,val+1+tot);
ll ans=0;
for(ll i=tot;i>=tot-3&&i>=1;i--){
if(val[i]>0) ans+=val[i];
else break;
}
ans+=a[u];
if(ans==0) printf("0\n");
else{
if(ans<0){
printf("-");
ans=-ans;
}
tot=0;
while(ans){
pri[++tot]=ans%2;
ans/=2;
}
for(ll i=tot;i>=1;i--){
printf("%lld",pri[i]);
}
printf("\n");
}
}
return 0;
}