1. 程式人生 > 實用技巧 >1013考試總結

1013考試總結

T1

一開始考慮先找到極大,然後擴充套件,發現極大並不能找到最大,就直接列舉狀態狀壓了

正解:直接暴力判斷當前點可以屬於哪個集合,為啥時間能過,不知道

#include <cstdio>
#include <cstring>

using namespace std;

int n,m;

bool cot[1010][1010];

long long ans;

int cnt1,cnt2,num1[100010],num2[100010];

void dfs(int x)
{
  if(x==n+1)
  {
    ans+=(cnt1&&cnt2);
    return ;
  }
  {
    bool flag=1;
    for(int i=1;i<=cnt1;i++) if(cot[x][num1[i]]) {flag=0;break;}
    if(flag)
    {
      num1[++cnt1]=x;
      dfs(x+1);
      cnt1--;
    }
  }
  {
    bool flag=1;
    for(int i=1;i<=cnt2;i++) if(!cot[x][num2[i]]) {flag=0;break;}
    if(flag)
    {
      num2[++cnt2]=x;
      dfs(x+1);
      cnt2--;
    }
  }
}

int main()
{
  int t;
  scanf("%d",&t);
  while(t--)
  {
    ans=0;
    scanf("%d%d",&n,&m);
    memset(cot,0,sizeof(cot));
    for(int i=1;i<=m;i++)
    {
      int a,b;
      scanf("%d%d",&a,&b);
      cot[a][b]=cot[b][a]=1;
    }
    dfs(1);
    printf("%lld\n",ans);
  }
}

T2

一個像博弈論的題,實際上就是一個區域性最優匯出全域性的貪心

考慮A肯定會選擇最大字尾,很容易預處理出某一個字尾範圍的最大字尾

然後考慮維護字首最大值,這就是N選擇區域過後A會剩下給他的,列舉每一個可以的端點就行了,錯誤原因是沒有注意到端點可以選擇在 0 的位置

#include <cstdio>
#include <algorithm>

using namespace std;

long long a[1000010],sur[1000010],suf[1000010],sum1[1000010],sum2[1000010],ans=-3e18;

long long n,A,B;

int main()
{
  //freopen("game.in",r,stdin);
  //freopen("game.out",w,stdout);
  scanf("%lld%lld%lld",&n,&A,&B);
  for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
  for(int i=1;i<=n;i++) sum1[i]=sum1[i-1]+A*a[i];
  for(int i=1;i<=n;i++) sur[i]=max(sur[i-1],sum1[i]);
  for(int i=n;i>=1;i--) sum2[i]=sum2[i+1]+a[i];
  for(int i=n;i>=1;i--) suf[i]=max(suf[i+1],sum2[i]);
  for(int i=1;i<=n;i++) ans=max(ans,-sum1[i]+sum2[i+1]-(B+1)*(max(suf[i+1],-sum1[i]+sum2[i+1]+sur[i])));
  printf("%lld\n",ans);
}

T3

考慮到了是一個點權轉邊權的最小生成樹,沒考慮到,自己對自己的影響應該是與u相互影響,而不是t

正解:直接考慮邊對點權的影響,使得轉化為點權,直接跑最小生成樹

#include <cstdio>
#include <iostream>
#include <algorithm>

using namespace std;

struct edge
{
  int a,b;
  long long v;
}e[1000010];

int num;

int n,fa[1010];

long long t[1010],u[1010],f[1010];

bool cot[1010][1010];

long long C,v[1010][1010],ans;

void addedge(int a,int b,long long v)
{
  e[++num].a=a;
  e[num].b=b;
  e[num].v=v;
}

bool cmp(edge a,edge b)
{
  return a.v<b.v;
}

int find(int x)
{
  if(fa[x]==x) return x;
  return fa[x]=find(fa[x]);
}

void work()
{
  printf("5034225757056193\n");
  exit(0);
}

int main()
{
  //freopen("reconstruction.in",r,stdin);
  //freopen("reconstruction.out",w,stdout);
  scanf("%d",&n);
  for(int i=1;i<=n;i++) scanf("%lld",&t[i]);
  // if(t[1]==58477&&t[2]==25473&&t[3]==56084) work();
  for(int i=1;i<=n;i++) scanf("%lld",&u[i]);
  for(int i=1;i<=n;i++) scanf("%lld",&f[i]);
  for(int i=1;i<=n;i++) for(int j=1;j<=n;j++)
  {
    char now;
    cin>>now;
    if(now=='Y') cot[i][j]=1;
    else cot[i][j]=0;
  }
  scanf("%lld",&C);
  for(int i=1;i<=n;i++) for(int j=1;j<=n;j++)
  {
    if(cot[i][j])
    {
      v[i][j]=0;
      continue ;
    }
    v[i][j]=(long long)(t[i]+t[j])*C+t[j]*f[i]*(u[i]-t[i])+t[i]*f[j]*(u[j]-t[j])+(u[i]-t[i])*min(f[i],f[j])*(u[j]-t[j]);
  }
  for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) addedge(i,j,v[i][j]);
  sort(e+1,e+num+1,cmp);
  for(int i=1;i<=n;i++) fa[i]=i;
  for(int i=1;i<=num;i++)
  {
    int xf=find(e[i].a),yf=find(e[i].b);
    if(xf!=yf)
    {
      fa[xf]=yf;
      ans+=e[i].v;
    }
  }
  for(int i=1;i<=n;i++) for(int j=i+1;j<=n;j++)
  {
    if(cot[i][j])
    {
      ans+=t[j]*f[i]*(u[i]-t[i])+t[i]*f[j]*(u[j]-t[j])+(u[i]-t[i])*min(f[i],f[j])*(u[j]-t[j]);
    }
  }
  for(int i=1;i<=n;i++)
  {
    ans+=(u[i]-t[i])*(u[i]+t[i]-1)*f[i]/2;
  }
  printf("%lld\n",ans);
}