简单的dp(dp专题)
题目链接:https://vjudge.net/contest/216347#problem/C
InputThe input contains multiple test cases.
For each test case, the first line cantains two integers N,M(1≤N,M≤1000)N,M(1≤N,M≤1000). The next line contains N integers. The next line followed M integers. All integers are between 1 and 1000.OutputFor each test case, output the answer mod 1000000007.Sample Input
3 2 1 2 3 2 1 3 2 1 2 3 1 2
Sample Output
2 3
#include<iostream> #include<stdio.h> #include<string.h> #include<cmath> #include<math.h> #include<algorithm> #include<set> typedef long long ll; using namespace std; const ll INF=1e9+7; //#define INF 1e9+7 ll dp[1100][1100]; int main() { ll n,m; ll a[1100],b[1100]; while(scanf("%I64d%I64d",&n,&m)!=EOF) { memset(dp,0,sizeof(dp)); for(int i=1;i<=n;i++) { scanf("%I64d",&a[i]); } for(int i=1;i<=m;i++) scanf("%I64d",&b[i]); for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) { if(a[i]!=b[j]) { dp[i][j]=(dp[i][j-1]+dp[i-1][j]-dp[i-1][j-1]+INF)%INF;//注意括号里面可能是负数,不加上会wa } else { dp[i][j]=(dp[i][j-1]+dp[i-1][j]+1)%INF; } } } printf("%I64d\n",dp[n][m]); } return 0; }
题目链接:https://vjudge.net/contest/231313#problem/E
By overall bandwidth (B) we mean the minimum of the bandwidths of the chosen devices in the communication system and the total price (P) is the sum of the prices of all chosen devices. Our goal is to choose a manufacturer for each device to maximize B/P.
Input
Output
Sample Input
1 3 3 100 25 150 35 80 25 2 120 80 155 40 2 100 100 120 110
Sample Output
0.649
题目大意:输入t,代表t组测试样例,输入n,代表有n 个设备,接下来n行,每行有一个num,代表有num个厂家,接着有num对数,分别代表b,p。每个设备选择一个厂家,最后求出b与sum的最大比值
,b是你选择的厂家里最小的b,sum是你选择的p的总和。
个人思路:最先想到dfs,直接暴力搜索,没想到数据这么小也超时了,然后猜想只能用dp来写了,因为不能剪枝,感觉自己对dp还是不熟,感觉要写出来了却还是差一点,最后搜了题解,看懂了
ac代码如下
#include<iostream> #include<stdio.h> #include<string.h> #include<cmath> #include<math.h> #include<algorithm> #include<set> typedef long long ll; using namespace std; const ll mod=1e9+7; #define INF 0x3f3f3f int dp[110][20000];//dp[i][j]代表从第1~i个厂家使得带宽为j的最小价格总和,因为题目没有说带宽的范围,我们假设最大20000 int main() { int t; scanf("%d",&t); while(t--) { int n; double ans=0; scanf("%d",&n); for(int i=1;i<=n;i++) { for(int j=0;j<=2000;j++) dp[i][j]=INF;//先把每一个都初始化为无穷大 } for(int i=1;i<=n;i++) { int num; scanf("%d",&num); for(int j=1;j<=num;j++) { int p,q; scanf("%d%d",&p,&q); if(i==1)//如果i=1的话,直接赋初值,因为没有上一个状态转移给i dp[i][p]=min(dp[i][p],q);//注意为啥要min(),因为可能dp[i][p]会有多次到达,所以取最小 else for(int k=0;k<=2000;k++) { if(dp[i-1][k]!=INF) { if(k<=p) { dp[i][k]=min(dp[i][k],dp[i-1][k]+q);//刚开始没有想到这里为什么也要min(),以为 //不要也行,提交wa了,后来看代码,因为上面有个for(j)的循环,同样dp[i][k]会有多次 } else { dp[i][p]=min(dp[i][p],dp[i-1][k]+q); } } } } } for(int i=0;i<=2000;i++) { if(dp[n][i]!=INF) { if(1.0*i/dp[n][i]>ans) ans=1.0*i/dp[n][i]; } } printf("%.3lf\n",ans); } return 0; }