第一组dp解题报告

t1

一开始还被这个给搞到了,突然发现问题和图片是不一样的(

这个的特点就在于每一个物品的贡献都是没有先后的,也就是说我可以把每一个物品都当作最后一个来消除影响

所以代码也很简单

#include <cstdio>
#include <cstring>

using namespace std;

int n,m;

long long v[2010];

long long f[2010],g[2010];

int main()
{
  scanf("%d%d",&n,&m);
  for(int i=1;i<=n;i++)
  {
    scanf("%d",&v[i]);
  }
  f[0]=1;
  for(int i=1;i<=n;i++)
  {
    for(int j=m;j>=v[i];j--) f[j]+=f[j-v[i]],f[j]%=10;
  }
  for(int i=1;i<=n;i++)
  {
    memcpy(g,f,sizeof(f));
    for(int j=v[i];j<=m;j++) g[j]-=g[j-v[i]],g[j]=(g[j]%10+10)%10;
    for(int j=1;j<=m;j++) printf("%d",g[j]%10);
    printf("
");
  }
}

太宰

t2(我把poj的跳了)

这个比较新颖,让我感觉到了背包不止可以做费用的问题

这方面来想背包性的dp就是对于两个渐进的状态的最优值的dp

比如这个题就是dp的联通性的问题

#include<bits/stdc++.h>

using namespace std;

int n,begin,maxlevel,ans;

int a[51],f[51][1001];

int main()
{
    scanf("%d%d%d",&n,&begin,&maxlevel);
    f[0][begin]=1;
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
    }
    for(int i=1;i<=n;i++)
    {
      for(int j=maxlevel;j>=0;j--)
      {
        if(j-a[i]>=0)
          f[i][j]=f[i][j]||f[i-1][j-a[i]];
        if(j+a[i]<=maxlevel)
          f[i][j]=f[i][j]||f[i-1][j+a[i]];
      }
    }
    for(int i=maxlevel;i>=1;i--) if(f[n][i]==1) {printf("%d",i);return 0;}
    printf("-1");
    return 0;
}

Uo4sxI.jpg

t3

这个还是比较有意思,首先可以看出询问和物品都可以离线的,只是这个(b)有一点难整

实际上这个可以直接当作我们要求的东西,我们以另一种眼光来看,背包实际上是一个状态路径的过程,他是将路径虚化了的图的遍历,既然如此我们的状态就可以看做点

那么我们实际只要求出我们可以从起始点到结束点的最优的方案,(b)也就迎刃而解

那就直接上代码吧

#include <cstdio>
#include <algorithm>

using namespace std;

struct th
{
  int a,b,c;
}sth[1000010];

struct query
{
  int m,k,s;
  int id;
}q[1000010];

int n,m;

int f[1000010];

bool ans[1000010];

bool cmp1(th a,th b)
{
  return a.a<b.a;
}

bool cmp2(query a,query b)
{
  return a.m<b.m;
}

int main()
{
  scanf("%d",&n);
  for(int i=1;i<=n;i++)
  {
    scanf("%d%d%d",&sth[i].c,&sth[i].a,&sth[i].b);
  }
  scanf("%d",&m);
  for(int i=1;i<=m;i++)
  {
    scanf("%d%d%d",&q[i].m,&q[i].k,&q[i].s);
    q[i].id=i;
  }
  sort(sth+1,sth+n+1,cmp1);
  sort(q+1,q+m+1,cmp2);
  int j=1;
  f[0]=1e9;
  for(int i=1;i<=m;i++)
  {
    while(j<=n&&sth[j].a<=q[i].m)
    {
      for(int k=100000;k>=sth[j].c;k--)
      {
        f[k]=max(f[k],min(f[k-sth[j].c],sth[j].b));
      }
      j++;
    }
    if(f[q[i].k]>(q[i].m+q[i].s)) ans[q[i].id]=1;
  }
  for(int i=1;i<=m;i++)
  {
    if(ans[i]) printf("TAK
");
    else printf("NIE
");
  }
}
原文地址:https://www.cnblogs.com/zzqdeco/p/13360499.html