动态规划——背包LISLCS
Posted SummerSky
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了动态规划——背包LISLCS相关的知识,希望对你有一定的参考价值。
问题 A: 导弹拦截
时间限制: 1 Sec 内存限制: 128 MB题目描述
某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统。但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意 的高度,但是以后每一发炮弹都不能高于前一发的高度。某天,雷达捕捉到敌国的导弹来袭。由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所 有的导弹。
输入导弹一次飞来的高度(雷达给出的高度不大于30000的正整数)。计算这套系统最多能拦截多少导弹。
输入
n颗依次飞来的导弹高度,导弹颗数<=1000。
输出
一套系统最多拦截的导弹数。
样例输入
样例输出
这题是一道裸的LIS,
f(n)表示1~n内最多拦截的导弹数。
有:f(n)=Max(f(i)+1)(i<n && a[i]>=a[j])
f值相等的我们只用保留a值最小的,再二分查找即可。
1 #include<iostream> 2 #include<algorithm> 3 #include<cstdio> 4 #include<cstring> 5 #include<cmath> 6 #include<cstdlib> 7 #include<vector> 8 using namespace std; 9 typedef long long ll; 10 typedef long double ld; 11 typedef pair<int,int> pr; 12 const double pi=acos(-1); 13 #define rep(i,a,n) for(int i=a;i<=n;i++) 14 #define per(i,n,a) for(int i=n;i>=a;i--) 15 #define Rep(i,u) for(int i=head[u];i;i=Next[i]) 16 #define clr(a) memset(a,0,sizeof(a)) 17 #define pb push_back 18 #define mp make_pair 19 #define fi first 20 #define sc second 21 #define pq priority_queue 22 #define pqb priority_queue <int, vector<int>, less<int> > 23 #define pqs priority_queue <int, vector<int>, greater<int> > 24 #define vec vector 25 ld eps=1e-9; 26 ll pp=1000000007; 27 ll mo(ll a,ll pp){if(a>=0 && a<pp)return a;a%=pp;if(a<0)a+=pp;return a;} 28 ll powmod(ll a,ll b,ll pp){ll ans=1;for(;b;b>>=1,a=mo(a*a,pp))if(b&1)ans=mo(ans*a,pp);return ans;} 29 void fre() { freopen("c://test//input.in", "r", stdin); freopen("c://test//output.out", "w", stdout); } 30 //void add(int x,int y,int z){ v[++e]=y; next[e]=head[x]; head[x]=e; cost[e]=z; } 31 int dx[5]={0,-1,1,0,0},dy[5]={0,0,0,-1,1}; 32 ll read(){ ll ans=0; char last=\' \',ch=getchar(); 33 while(ch<\'0\' || ch>\'9\')last=ch,ch=getchar(); 34 while(ch>=\'0\' && ch<=\'9\')ans=ans*10+ch-\'0\',ch=getchar(); 35 if(last==\'-\')ans=-ans; return ans; 36 } 37 int a[10000],b[10000]; 38 const int oo=1e+08; 39 int find (int l,int r,int val){ 40 while (l<r){ 41 int mid=(l+r)>>1; 42 if (b[mid]<val) r=mid; 43 else l=mid+1; 44 } 45 return r; 46 } 47 int main() 48 { 49 int n=read(),nu=0; 50 for (int i=1;i<=n;i++) a[i]=read(); 51 for (int i=1;i<=n;i++){ 52 int j=find(1,nu+1,a[i]); 53 if (nu+1==j) b[++nu]=a[i]; 54 else b[j]=a[i]; 55 } 56 printf("%d",nu); 57 return 0; 58 }
问题 B: 友好城市
时间限制: 1 Sec 内存限制: 128 MB题目描述
Palmia国有一条横贯东西的大河,河有笔直的南北两岸,岸上各有位置不同的N个城市。北岸的每个城市有且仅有一个友好城市在南岸,而且不同城市的友好城市不相同。
每对友好城市都向政府申请在河上开辟一条直线航道连接两个城市,但是由于河上雾太大,政府决定避免任意两条航道交叉,以避免事故。编程帮助政府作出一些批准和拒绝申请的决定,使得在保证任意两条航线不相交的情况下,被批准的申请尽量多。
输入
第1行,一个整数N(1<=N<=50000,表示城市数。
第2行到第n+1行,每行两个整数,中间用1个空格隔开,分别表示南岸和北岸的一对友好城市的左边。(0<=xi<=10000)
输出
仅一行,输出一个整数,政府所能批准的最多申请书。
样例输入
样例输出
题目中说不能相交,所以可以先将一维排序,在比较另一维,
然后我们就见到了熟悉的东西——LIS.
1 #include<iostream> 2 #include<algorithm> 3 #include<cstdio> 4 #include<cstring> 5 #include<cmath> 6 #include<cstdlib> 7 #include<vector> 8 using namespace std; 9 typedef long long ll; 10 typedef long double ld; 11 typedef pair<int,int> pr; 12 const double pi=acos(-1); 13 #define rep(i,a,n) for(int i=a;i<=n;i++) 14 #define per(i,n,a) for(int i=n;i>=a;i--) 15 #define Rep(i,u) for(int i=head[u];i;i=Next[i]) 16 #define clr(a) memset(a,0,sizeof(a)) 17 #define pb push_back 18 #define mp make_pair 19 #define fi first 20 #define sc second 21 #define pq priority_queue 22 #define pqb priority_queue <int, vector<int>, less<int> > 23 #define pqs priority_queue <int, vector<int>, greater<int> > 24 #define vec vector 25 ld eps=1e-9; 26 ll pp=1000000007; 27 ll mo(ll a,ll pp){if(a>=0 && a<pp)return a;a%=pp;if(a<0)a+=pp;return a;} 28 ll powmod(ll a,ll b,ll pp){ll ans=1;for(;b;b>>=1,a=mo(a*a,pp))if(b&1)ans=mo(ans*a,pp);return ans;} 29 void fre() { freopen("c://test//input.in", "r", stdin); freopen("c://test//output.out", "w", stdout); } 30 //void add(int x,int y,int z){ v[++e]=y; next[e]=head[x]; head[x]=e; cost[e]=z; } 31 int dx[5]={0,-1,1,0,0},dy[5]={0,0,0,-1,1}; 32 ll read(){ ll ans=0; char last=\' \',ch=getchar(); 33 while(ch<\'0\' || ch>\'9\')last=ch,ch=getchar(); 34 while(ch>=\'0\' && ch<=\'9\')ans=ans*10+ch-\'0\',ch=getchar(); 35 if(last==\'-\')ans=-ans; return ans; 36 } 37 #define N 50005 38 int b[N]; 39 struct node 40 { 41 int x,y; 42 }a[N]; 43 bool cmp(node a,node b){ 44 return a.x<b.x||a.x==b.x&&b.x<b.y; 45 } 46 const int oo=1e+08; 47 int find(int l,int r,int val){ 48 b[r]=oo; 49 while (l<r){ 50 int mid=(l+r)>>1; 51 if (b[mid]>val) r=mid; 52 else l=mid+1; 53 } 54 return r; 55 } 56 int main() 57 { 58 int n=read(),nu=0; 59 for (int i=1;i<=n;i++) a[i].x=read(),a[i].y=read(); 60 sort(a+1,a+n+1,cmp); 61 for (int i=1;i<=n;i++){ 62 int j=find(1,nu+1,a[i].y); 63 if (nu+1==j) b[++nu]=a[i].y; 64 else b[j]=a[i].y; 65 } 66 printf("%d\\n",nu); 67 return 0; 68 }
问题 C: 0/1背包
时间限制: 1 Sec 内存限制: 128 MB题目描述
一个旅行者有一个最多能装m公斤物品的背包,现在有n件物品,它们的重量分别是w1,w2,…,wn,它们的价值分别为c1,c2,…,cn。若每件物品只有一件,求旅行者能获得的最大总价值。
输入
第一行:两个整数,m(背包容量,m<=200)和n(物品数量,n<=30)。
第二~n+1行:每行两个整数wi,ci,表示每个物品的重量和价值。
输出
一个数据,表示最大总价值。
样例输入
样例输出
只是最初始的背包问题。
f[i][v]表示前i件物品恰放入一个容量为v的背包可以获得的最大价值。
f[i][v]=max(f[i-1][v],f[i-1][v-Ci]+Wi);
而每次主循环中以v的递减顺序计算 f[v],这样才
能保证计算f[v]时f[v-Ci]保存的是状态f[i-1][v-Ci]的值。
1 #include<iostream> 2 #include<algorithm> 3 #include<cstdio> 4 #include<cstring> 5 #include<cmath> 6 #include<cstdlib> 7 #include<vector> 8 using namespace std; 9 typedef long long ll; 10 typedef long double ld; 11 typedef pair<int,int> pr; 12 const double pi=acos(-1); 13 #define rep(i,a,n) for(int i=a;i<=n;i++) 14 #define per(i,n,a) for(int i=n;i>=a;i--) 15 #define Rep(i,u) for(int i=head[u];i;i=Next[i]) 16 #define clr(a) memset(a,0,sizeof(a)) 17 #define pb push_back 18 #define mp make_pair 19 #define fi first 20 #define sc second 21 #define pq priority_queue 22 #define pqb priority_queue <int, vector<int>, less<int> > 23 #define pqs priority_queue <int, vector<int>, greater<int> > 24 #define vec vector 25 ld eps=1e-9; 26 ll pp=1000000007; 27 ll mo(ll a,ll pp){if(a>=0 && a<pp)return a;a%=pp;if(a<0)a+=pp;return a;} 28 ll powmod(ll a,ll b,ll pp){ll ans=1;for(;b;b>>=1,a=mo(a*a,pp))if(b&1)ans=mo(ans*a,pp);return ans;} 29 void fre() { freopen("c://test//input.in", "r", stdin); freopen("c://test//output.out", "w", stdout); } 30 //void add(int x,int y,int z){ v[++e]=y; next[e]=head[x]; head[x]=e; cost[e]=z; } 31 int dx[5]={0,-1,1,0,0},dy[5]={0,0,0,-1,1}; 32 ll read(){ ll ans=0; char last=\' \',ch=getchar(); 33 while(ch<\'0\' || ch>\'9\')last=ch,ch=getchar(); 34 while(ch>=\'0\' && ch<=\'9\')ans=ans*10+ch-\'0\',ch=getchar(); 35 if(last==\'-\')ans=-ans; return ans; 36 } 37 #define N 300 38 int w[N],c[N],f[N]; 39 int main() 40 { 41 int m=read(),n=read(),Max=0; 42 for (int i=1;i<=n;i++) w[i]=read(),c[i]=read(); 43 for (int i=1;i<=n;i++) 44 for (int j=m;j>=w[i];j--) 45 f[j]=max(f[j],f[j-w[i]]+c[i]),Max=max(Max,f[j]); 46 printf("%d\\n",Max); 47 return 0; 48 }
问题 D: P1013
时间限制: 1 Sec 内存限制: 128 MB题目描述
" 找啊找啊找GF,找到一个好GF,吃顿饭啊拉拉手,你是我的好GF.再见." " 诶,别再见啊..." 七夕...七夕...七夕这个日子,对于sqybi这种单身的菜鸟来说是多么的痛苦...虽然他听着这首叫做" 找啊找啊找GF" 的歌,他还是很痛苦.为了避免这种痛苦,sqybi决定要给自己找点事情干.他去找到了七夕模拟赛的负责人zmc MM,让她给自己一个出题的任务.经过几天的死缠烂打,zmc MM终于同意了. 但是,拿到这个任务的sqybi发现,原来出题比单身更让人感到无聊-_-....所以,他决定了,要在出题的同时去办另一件能够使自己不无聊的事情--给自己找GF. sqybi现在看中了n个MM,我们不妨把她们编号1到n.请MM吃饭是要花钱的,我们假设请i号MM吃饭要花rmb[i]块大洋.而希望骗MM当自己GF是要费人品的,我们假设请第i号MM吃饭试图让她当自己GF的行为(不妨称作泡该MM)要耗费rp[i]的人品.而对于每一个MM来说,sqybi都有一个对应的搞定她的时间,对于第i个MM来说叫做time[i]. sqybi保证自己有足够的魅力用time[i]的时间搞定第i个MM^_^. sqybi希望搞到尽量多的MM当自己的GF,这点是毋庸置疑的.但他不希望为此花费太多的时间(毕竟七夕赛的题目还没出),所以他希望在保证搞到MM数量最多的情况下花费的总时间最少. sqybi现在有m块大洋,他也通过一段时间的努力攒到了r的人品(这次为模拟赛出题也攒rp哦~~).他凭借这些大洋和人品可以泡到一些MM.他想知道,自己泡到最多的MM花费的最少时间是多少. 注意sqybi在一个时刻只能去泡一个MM--如果同时泡两个或以上的MM的话,她们会打起来的...
输入
输入的第一行是n,表示sqybi看中的MM数量.接下来有n行,依次表示编号为1, 2, 3, ..., n的一个MM的信息.每行表示一个MM的信息,有三个整数:rmb, rp和time.最后一行有两个整数,分别为m和r.
输出
你只需要输出一行,其中有一个整数,表示sqybi在保证MM数量的情况下花费的最少总时间是多少.
样例输入
样例输出
提示
数据规模 对于20%数据,1< =n< =10; 对于100%数据,1< =rmb< =100,1< =rp< =100,1< =time< =1000; 对于100%数据,1< =m< =100,1< =r< =100,1< =n< =100. Hint sqybi说:如果题目里说的都是真的就好了... sqybi还说,如果他没有能力泡到任何一个MM,那么他就不消耗时间了(也就是消耗的时间为0),他要用这些时间出七夕比赛的题来攒rp... 出题人 sqybi GG
用背包的基本做法,f[i][j]表示用了i的钱,j的rp最多能泡到的MM数。
g[i][j]表示能泡到最多数量的最小代价。
转移:
if
(f[j][k]==f[j-w[i]][k-r[i]]+1) t[j][k]=min(t[j][k],t[j-w[i]][k-r[i]]+c[i]);
else
if
(f[j][k]<f[j-w[i]][k-r[i]]+1) f[j][k]=f[j-w[i]][k-r[i]]+1,t[j][k]=t[j-w[i]][k-r[i]]+c[i];
1 #include<iostream> 2 #include<algorithm> 3 #include<cstdio> 4 #include<cstring> 5 #include<cmath> 6 #include<cstdlib> 7 #include<vector> 8 using namespace std; 9 typedef long long ll; 10 typedef long double ld; 11 typedef pair<int,int> pr; 12 const double pi=acos(-1); 13 #define rep(i,a,n) for(int i=a;i<=n;i++) 14 #define per(i,n,a) for(int i=n;i>=a;i--) 15 #define Rep(i,u) for(int i=head[u];i;i=Next[i]) 16 #define clr(a) memset(a,0,sizeof(a)) 17 #define pb push_back 18 #define mp make_pair 19 #define fi first 20 #define sc second 21 #define pq priority_queue 22 #define pqb priority_queue <int, vector<int>, less<int> > 23 #define pqs priority_queue <int, vector<int>, greater<int> > 24 #define vec vector 25 ld eps=1e-9; 26 ll pp=1000000007; 27 ll mo(ll a,ll pp){if(a>=0 && a<pp)return a;a%=pp;if(a<0)a+=pp;return a;} 28 ll powmod(ll a,ll b,ll pp){ll ans=1;for(;b;b>>=1,a=mo(a*a,pp))if(b&1)ans=mo(ans*a,pp);return ans;} 29 void fre() { freopen("c://test//input.in", "r", stdin); freopen("c://test//output.out", "w", stdout); } 30 //void add(int x,int y,int z){ v[++e]=y; next[e]=head[x]; head[x]=e; cost[e]=z; } 31 int dx[5]={0,-1,1,0,0},dy[5]={0,0,0,-1,1}; 32 ll read(){ ll ans=0; char last=\' \',ch=getchar(); 33 while(ch<\'0\' || ch>\'9\')last=ch,ch=getchar(); 34 while(ch>=\'0\' && ch<=\'9\')ans=ans*10+ch-\'0\',ch=getchar(); 35 if(last==\'-\')ans=-ans; return ans; 36 } 37 const int oo=1e+08; 38 #define N 1000 39 int f[N][N],t[N][N],w[N],r[N],c[N]; 40 int main() 41 { 42 int n=read(); 43 for (int i=1;i<=n;i++) w[i]=read(),r[i]=read(),c[i]=read(); 44 int M=read(),R=read(); 45 for (int i=1;i<=n;i++) 46 for (int j=M;j>=w[i];j--) 47 for (int k=R;k>=r[i];k--){ 48 if (f[j][k]==f[j-w[i]][k-r[i]]+1) t[j][k]=min(t[j][k],t[j-w[i]][k-r[i]]+c[i]); 49 else if (f[j][k]<f[j-w[i]][k-r[i]]+1) f[j][k]=f[j-w[i]][k-r[i]]+1,t[j][k]=t[j-w[i]][k-r[i]]+c[i]; 50 } 51 printf("%d\\n",t[M][R]); 52 return 0; 53 }
问题 E: P1034
时间限制: 1 Sec 内存限制: 128 MB题目描述
尼克每天上班之前都连接上英特网,接收他的上司发来的邮件,这些邮件包含了尼克主管的部门当天要完成的全部任务,每个任务由一个开始时刻与一个持续时间构成。 尼克的一个工作日为N分钟,从第一分钟开始到第N分钟结束。当尼克到达单位后他就开始干活。如果在同一时刻有多个任务需要完成,尼克可以任选其中的一个来做,而其余的则由他的同事完成,反之如果只有一个任务,则该任务必需由尼克去写成,假如某些任务开始时刻尼克正在工作,则这些任务也由尼克的同事完成。如果某任务于第P分钟开始,持续时间为T分钟,则该任务将在第P+T-1分钟结束。 写一个程序计算尼克应该如何选取任务,才能获得最大的空暇时间。
输入
输入数据第一行包含两个用空格隔开的整数N和K,1≤N≤10000,1≤K≤10000,N表示尼克的工作时间,单位为分,K表示任务总数。 接下来共有K行,每一行有两个用空格隔开的整数P和T,表示该任务从第P分钟开始,持续时间为T分钟,其中1≤P≤N,1≤P+T-1≤N。
输出
输出文件仅一行包含一个整数表示尼克可能获得的最大空暇时间。
样例输入
样例输出
提示
某ACM经典题
这道题如果顺推的话很容易发现不知道前面的是否用做。
我们就想到了逆推,f[i]表示i~n的空闲时间,
如果当前位置有任务的话就从后面转移过来,
否则就后面一位加1转移过来。