• 【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
    ",i);
    143                 flag=1;
    144                 break;
    145             }
    146         }
    147          if(!flag) printf("-1
    ");
    148     }
    149     return 0;
    150 }
  • 相关阅读:
    java基础知识(一)- 数据类型
    Java基础知识-去重
    java基础知识-冒泡排序
    Java排序方法sort的使用详解
    Java面试题-字符串操作
    Map.Entry遍历Map
    Java中String的用法
    Java循环控制语句-switch
    API文档打开显示'已取消到该网页的导航'的解决方法
    CentOS6.5 安装snort
  • 原文地址:https://www.cnblogs.com/myx12345/p/11877801.html
Copyright © 2020-2023  润新知