cdoj1633 去年春恨却来时,落花人独立,微雨燕双飞

地址:http://acm.uestc.edu.cn/#/problem/show/1633

题目:

去年春恨却来时,落花人独立,微雨燕双飞

Time Limit: 3000/1000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others)

给你一个大小为n的集合S,集合里有n个互不相同正整数.
q个询问,每次询问是否能选择S中的一些数字 ( 同一个数字可以选择多次,也可以任何数字都不选),使它们相加的和为m.

Input

第一行一个数n(1n2000),表示集合S的大小.
第二行n个数,第ii个数ai(1ai50000)表示集合S中的第ii个数.
第三行一个数q(1q10000),表示询问次数.
接下来q行,每行一个数m(0≤m≤1000000000),表示该次询问的数.

Output

每次询问输出一行,如果存在和为m的方法,输出YES,否则输出NO.

Sample input and output

Sample InputSample Output
3
2 4 9
4
6
7
18
25
YES
NO
YES
YES

Hint

对于第一个询问,存在2+2+2=6,所以输出YES
对于第一个询问,无法构造,输出NO
对于第三个询问,存在9+9=18,所以输出YES
对于第四个询问,存在2+2+4+4+4+9=25,所以输出YES

Source

2017 UESTC Training for Graph Theory
 
思路:
  设集合中最小的数为p。假如现在知道x能被表示出来,那么x+ai必然也能够被表示出来。
  记d[x]为所能表示的所有模p为x的数中的最小值,那么d[x]+k*p的所有数也必然能被表示出来。
  所以考虑模p的所有剩余系,可以判断任意数字是否可以被表示。
  然后题目就转化成了求d[x]的最短路问题。
 1 #include <bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 #define MP make_pair
 6 #define PB push_back
 7 typedef long long LL;
 8 typedef pair<int,int> PII;
 9 const double eps=1e-8;
10 const double pi=acos(-1.0);
11 const int K=5e4+7;
12 const int mod=1e9+7;
13 
14 int n,m;
15 int v[K],d[K],vis[K],mi=mod;
16 void spfa(void)
17 {
18     memset(d,0x3f3f3f3f,sizeof d);
19     queue<int>q;
20     q.push(0),d[0]=0,vis[0]=1;
21     while(q.size())
22     {
23        int x=q.front();
24        q.pop(),vis[x]=0;
25        for(int i=1;i<=n;i++)
26        {
27            int y=(x+v[i])%mi;
28            if(d[x]+v[i]<d[y])
29            {
30                d[y]=d[x]+v[i];
31                if(!vis[y])  q.push(y),vis[y]=1;
32            }
33        }
34     }
35 }
36 int main(void)
37 {
38     scanf("%d",&n);
39     for(int i=1;i<=n;i++)
40         scanf("%d",v+i),mi=min(mi,v[i]);
41     spfa();
42     scanf("%d",&m);
43     int x;
44     while(m--)
45     {
46         scanf("%d",&x);
47         if(d[x%mi]<=x)  printf("YES\n");
48         else    printf("NO\n");
49     }
50     return 0;
51 }

 

  
posted @ 2017-08-04 01:19  weeping  阅读(549)  评论(0编辑  收藏  举报