【CodeChef】LECOINS(同余最短路,背包DP)

题意:给定n个物品,每个物品可以取无限次,每个物品有两种属性:价值v和颜色c

现在有q个询问,每次询问是否能取出价值和为S的方案,如有多解输出不同颜色种数的最大值

 题意:看到BZOJ评论区有好心人说CC上有上一题的加强版就写了一下

首先按颜色分组,每组中取或不取只有0/1

对于每组内部就是一个同余最短路

设dp[i][j][k]为当前组不取(0)/取(1),当前共有j种不同的,模意义下和为k的最小总价值

每次建图跑SPFA转移,每次询问时暴力从大到小枚举颜色种数判断是否有解

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 typedef long long ll;
  4 typedef unsigned int uint;
  5 typedef unsigned long long ull;
  6 typedef long double ld;
  7 typedef pair<int,int> PII;
  8 typedef pair<ll,ll> Pll;
  9 typedef vector<int> VI;
 10 typedef vector<PII> VII;
 11 typedef pair<ll,ll>P;
 12 #define N  200010
 13 #define M  6000010
 14 //#define INF 1e9
 15 #define fi first
 16 #define se second
 17 #define MP make_pair
 18 #define pb push_back
 19 #define pi acos(-1)
 20 #define mem(a,b) memset(a,b,sizeof(a))
 21 #define rep(i,a,b) for(int i=(int)a;i<=(int)b;i++)
 22 #define per(i,a,b) for(int i=(int)a;i>=(int)b;i--)
 23 #define lowbit(x) x&(-x)
 24 #define Rand (rand()*(1<<16)+rand())
 25 #define id(x) ((x)<=B?(x):m-n/(x)+1)
 26 #define ls p<<1
 27 #define rs p<<1|1
 28 #define fors(i) for(auto i:e[x]) if(i!=p)
 29 
 30 const int MOD=1e8+7,inv2=(MOD+1)/2;
 31       int p=1e4+7;
 32       double eps=1e-8;
 33       int dx[4]={-1,1,0,0};
 34       int dy[4]={0,0,-1,1};
 35 
 36 struct arr
 37 {
 38     int x,y;
 39 }a[N];
 40 
 41 bool cmp(arr a,arr b)
 42 {
 43     return a.y<b.y;
 44 }
 45 
 46 struct node
 47 {
 48     int x,y,z;
 49     node(){}
 50     node(int a,int b,int c){x=a,y=b,z=c;}
 51 }q[14000010];
 52 
 53 ll dis[2][35][N],INF;
 54 int vis[2][35][N],mn,c;
 55 
 56 int read()
 57 {
 58    int v=0,f=1;
 59    char c=getchar();
 60    while(c<48||57<c) {if(c=='-') f=-1; c=getchar();}
 61    while(48<=c&&c<=57) v=(v<<3)+v+v+c-48,c=getchar();
 62    return v*f;
 63 }
 64 
 65 ll readll()
 66 {
 67    ll v=0,f=1;
 68    char c=getchar();
 69    while(c<48||57<c) {if(c=='-') f=-1; c=getchar();}
 70    while(48<=c&&c<=57) v=(v<<3)+v+v+c-48,c=getchar();
 71    return v*f;
 72 }
 73 
 74 void spfa(int now)
 75 {
 76     int t=0,w=1;
 77     q[1]=node(0,0,0);
 78     vis[0][0][0]=1;
 79     rep(i,0,1)
 80      rep(j,1,c)
 81       rep(k,0,mn-1)
 82        if(dis[i][j][k]!=INF)
 83        {
 84            w++;
 85            q[w]=node(i,j,k);
 86            vis[i][j][k]=1;
 87        }
 88     while(t<w)
 89     {
 90         t++;
 91         int x=q[t].x,y=q[t].y,z=q[t].z;
 92         vis[x][y][z]=0;
 93         int A=1,B=y+1-x,C=(z+now)%mn;
 94         if(dis[x][y][z]+now<dis[A][B][C])
 95         {
 96             dis[A][B][C]=dis[x][y][z]+now;
 97             if(!vis[A][B][C])
 98             {
 99                 w++;
100                 q[w]=node(A,B,C);
101                 vis[A][B][C]=1;
102             }
103         }
104 
105     }
106 }
107 
108 int main()
109 {
110     //freopen("1.in","r",stdin);
111     //freopen("1.out","w",stdout);
112     int n=read();
113     mn=1e9;
114     rep(i,1,n) a[i].x=read(),a[i].y=read(),mn=min(mn,a[i].x);
115     sort(a+1,a+n+1,cmp);
116     mem(dis,0x3f);
117     INF=dis[0][0][0];
118     c=1;
119     dis[0][0][0]=0;
120     rep(i,0,n-1)
121     {
122         if(a[i].y!=a[i+1].y)
123         {
124             rep(j,1,c)
125              rep(k,0,mn-1) dis[0][j][k]=min(dis[0][j][k],dis[1][j][k]);
126         }
127         spfa(a[i+1].x);
128         if(a[i].y!=a[i+1].y) c++;
129     }
130     rep(j,1,c)
131      rep(k,0,mn-1) dis[0][j][k]=min(dis[0][j][k],dis[1][j][k]);
132     int Q=read();
133     while(Q--)
134     {
135         ll x=readll();
136         int u=x%mn;
137         int flag=0;
138         per(i,n,1)
139         {
140             if(dis[0][i][u]<=x)
141             {
142                 printf("%d\n",i);
143                 flag=1;
144                 break;
145             }
146         }
147          if(!flag) printf("-1\n");
148     }
149     return 0;
150 }

猜你喜欢

转载自www.cnblogs.com/myx12345/p/11877801.html