【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 }
null