任何东西题目还是要做滴~
POJ 3624
http://poj.org/problem?id=3624
我刚开始用了结构体来做,结果就MLE了。唉,看了别人的AC代码发现就数组,后来查了一下,发现结构体用不好就特别占内存
1 #include <cstdio> 2 #include <cstring> 3 4 using namespace std; 5 6 int n,m,w,v; 7 const int N = 13000; 8 int dp[N] = {}; 9 10 int main(){ 11 scanf("%d%d",&n,&m); 12 memset(dp,0,sizeof(dp)); 13 for(int i = 1;i <= n;i++){ 14 scanf("%d%d",&w,&v); 15 for(int j = m;j >= w;j--){ 16 int tmp = dp[j-w]+v; 17 if(tmp > dp[j]){ 18 dp[j] = tmp; 19 } 20 } 21 } 22 printf("%d\n",dp[m]); 23 }
POJ 3628
http://poj.org/problem?id=3628
这道题刚开始也MLE,真想友尽。
每个数据都是long long,然后申请了20000000个数组空间,算算也是超内存了,然后还memset了一遍,据说这个很占内存?
后来想想反正没有多组数据测试,而且全局申请的变量默认是0,就直接注释掉了。
刚开始直接把每个数据都算了一遍都往原数组存,估计就是这里MLE了
我看了别人的AC代码,另外开了一个数组,估计有很多空出来。
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 5 using namespace std; 6 7 const int N = 20000000 + 3; 8 9 int n,b,a,s; 10 int h[20 + 3] = {}; 11 int dp[N] = {}; 12 13 int main(){ 14 scanf("%d%d",&n,&b); 15 //memset(h,0,sizeof(h)); 16 for(int i = 1;i <= n;i++){ 17 scanf("%d",&h[i]); 18 s += h[i]; 19 } 20 for(int i = 1;i <= n;i++){ 21 for(int j = s;j >= h[i];j--){ 22 dp[j] = max(dp[j],dp[j-h[i]]+h[i]); 23 } 24 } 25 int minn = 10000000; 26 for(int i = s;i >= b;i--){ 27 if(dp[i] - b < minn && dp[i] - b >= 0){ 28 minn = dp[i] -b; 29 } 30 } 31 printf("%d\n",minn); 32 }
POJ 1837
http://poj.org/problem?id=1837
这道题刚开始题意都看不懂,因为英文实在太菜了T_T
后来直接搜题解,看到这个图瞬间懂了(出处:http://blog.csdn.net/hopeztm/article/details/7858622)
就是让两端平衡而已,只不过杆子不一定只有两根。
然后又看了一篇博客(http://www.cnblogs.com/kedebug/archive/2013/01/22/2871707.html)总算看懂
其中我看了很多人的代码,都写着15000和7500.我想了很久才想通这是怎么来的。
假设我们把所有的东西都挂在一端一根杆子上,最大的C*最大的G*最大的单个物体的重量 = 15 * 20 * 25 = 15000
我敢说绝大多数的博客没有解释这15000是怎么来的(自恋脸),好吧,我的猪脑太笨了
接着我们首先把7500当成中间状态,因为左边的是负数,这样我们再分别往左右两边挂东西。
下面我们把话筒交给dp~
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 5 #define MAXN 15000 6 7 using namespace std; 8 9 const int N = 25; 10 11 int c,g; 12 int a[N],b[N]; 13 int dp[N][MAXN] = {}; 14 15 16 int main(){ 17 scanf("%d%d",&c,&g); 18 for(int i = 1; i <= c;i++){ 19 scanf("%d",&a[i]); 20 } 21 for(int i = 1;i <= g;i++){ 22 scanf("%d",&b[i]); 23 } 24 memset(dp,0,sizeof(dp)); 25 dp[0][MAXN>>1] = 1; 26 27 for(int i = 1;i <= g;i++){ 28 for(int j = 1;j <= MAXN;j++){ 29 if(dp[i-1][j]){ 30 for(int k = 1;k <= c;k++){ 31 dp[i][j + a[k]*b[i]] += dp[i-1][j]; 32 } 33 } 34 } 35 } 36 printf("%d\n",dp[g][MAXN>>1]); 37 }
POJ 1948
http://poj.org/problem?id=1948
最近POJ国内老抽风,国外就可以上去,哼
细节要注意比较多,WA了好几次
1 #include <cstdio> 2 #include <iostream> 3 #include <cmath> 4 #include <cstring> 5 #include <queue> 6 #include <vector> 7 #include <algorithm> 8 9 #define rep(i,a,n) for(int i = a;i < n;i++) 10 #define per(i,n,a) for(int i = n-1;i >=a;i--) 11 #define pb push_back 12 #define VI vector<int> 13 #define QI queue<int> 14 15 typedef long long ll; 16 17 using namespace std; 18 19 const int N = 40 + 5; 20 const int M = 800 + 5; 21 22 int n; 23 int a[N] = {}; 24 bool dp[M][M] = {}; 25 double half,sum; 26 27 bool check(int a,int b,int c){ 28 if(a + b <= c || a + c <= b || b + c <= a){ 29 return false; 30 } 31 else{ 32 return true; 33 } 34 } 35 36 int main(){ 37 while(~scanf("%d",&n)){ 38 sum = 0.0; 39 rep(i,0,n){ 40 scanf("%d",&a[i]); 41 sum += a[i]; 42 } 43 half = sum / 2; 44 memset(dp,0,sizeof(dp)); 45 dp[0][0] = true; 46 rep(i,0,n){ 47 per(j,half+1,0){ 48 per(k,half+1,0){ 49 if(j >= a[i] && dp[j - a[i]][k]){ 50 dp[j][k] = true; 51 } 52 if(k >= a[i] && dp[j][k - a[i]]){ 53 dp[j][k] = true; 54 } 55 } 56 } 57 } 58 int maxn = 0; 59 rep(i,1,half){ 60 rep(j,1,half){ 61 if(dp[i][j]){ 62 double r = sqrt(half*(half-i)*(half-j)*(half-(sum-i-j)))*100; 63 maxn = (maxn<=(int)r?(int)r:maxn); 64 } 65 } 66 } 67 printf("%d\n",maxn==0?-1:maxn); 68 } 69 return 0; 70 }
POJ 3903
http://poj.org/problem?id=3903
因为题目看不懂就去搜了题解,知道了最长上升子序列(http://baike.baidu.com/subview/770542/15946409.htm)是什么
有两种时间复杂度的算法。我故意测试了时间复杂度是O(n^2)的,果然超时了。算了一下,10^10次,早就超时了
这道题目还要用到二分,二分的时间复杂度是O(nlogn),算了一下大概是5*10^5次,在POJ是63MS,不算快差不多是这个速度。看到题目里还有人是0MS的,估计还有什么技巧
顺便记一下操作符>>的注意事项:>>的优先级比+的小
所以原来我想表达(x+y)>>1的意思的,我就错误地写成了x+(y-x)>>1,其实这句话结果就是y>>1,所以要写成x+(y-x)/2。
学C的时候基础没有打好,就变成了现在这个下场T_T
1 #include <cstdio> 2 #include <iostream> 3 #include <cmath> 4 #include <cstring> 5 #include <queue> 6 #include <vector> 7 #include <algorithm> 8 9 #define rep(i,a,n) for(int i = a;i < n;i++) 10 #define per(i,n,a) for(int i = n-1;i >=a;i--) 11 #define pb push_back 12 #define VI vector<int> 13 #define QI queue<int> 14 15 typedef long long ll; 16 17 using namespace std; 18 19 int n; 20 const int N = 100000 + 5; 21 int a[N] = {},dp[N] = {}; 22 23 int binary_search(int x,int y,int q){ 24 while(x <= y){ 25 int mid = (x + y) >> 1; 26 //int mid = x + (y - x)>>1; 27 //int mid = x + (y - x)/2; 28 if(dp[mid] >= q){ 29 y = mid - 1; 30 } 31 else{ 32 x = mid + 1; 33 } 34 } 35 return x; 36 } 37 38 int main(){ 39 while(~scanf("%d",&n)){ 40 rep(i,0,n){ 41 scanf("%d",&a[i]); 42 } 43 rep(i,0,n){ 44 dp[i] = 0; 45 } 46 int len = 0; 47 rep(i,0,n){ 48 if(dp[len] < a[i]){ 49 dp[++len] = a[i]; 50 } 51 else{ 52 int j = binary_search(0,len,a[i]); 53 dp[j] = a[i]; 54 } 55 } 56 printf("%d\n",len); 57 } 58 return 0; 59 }
HDU 1203
http://acm.hdu.edu.cn/showproblem.php?pid=1203
水题,本来没怎么考虑空间复杂度,MLE了一次。
然后后来忘记每次都要memset,贡献了一次WA
最重要的是:你有1亿美元你还愁读什么学校?!直接哈佛啊?!你还读什么书?!
1 #include <cstdio> 2 #include <iostream> 3 #include <cmath> 4 #include <cstring> 5 #include <queue> 6 #include <vector> 7 #include <algorithm> 8 9 #define rep(i,a,n) for(int i = a;i < n;i++) 10 #define per(i,n,a) for(int i = n-1;i >=a;i--) 11 #define pb push_back 12 #define VI vector<int> 13 #define QI queue<int> 14 15 typedef long long ll; 16 17 using namespace std; 18 19 int n,m; 20 const int N = 10000 + 5; 21 int a[N] = {}; 22 double b[N] = {}; 23 double dp[N] = {}; 24 25 int main(){ 26 while(~scanf("%d%d",&n,&m),n+m > 0){ 27 rep(i,0,m){ 28 scanf("%d%lf",&a[i],&b[i]); 29 } 30 memset(dp,0.0,sizeof(dp)); 31 rep(i,1,m+1){ 32 per(j,n+1,a[i-1]){ 33 dp[j] = max(dp[j],1-((1-dp[j-a[i-1]])*(1-b[i-1]))); 34 } 35 } 36 /* 37 rep(i,0,m+1){ 38 rep(j,0,n+1){ 39 cout<<dp[i][j]<<i<<" "<<j<<" "; 40 }puts(""); 41 } 42 */ 43 printf("%.1f%%\n",dp[n]*100.0); 44 } 45 return 0; 46 }
HDU 2955
http://acm.hdu.edu.cn/showproblem.php?pid=2955
这道题目因为本人的猪脑,认为把被抓住率加起来就可以了。无限WA
后来看了别人题解才知道是逃脱率乘起来
1 #include <cstdio> 2 #include <iostream> 3 #include <cmath> 4 #include <cstring> 5 #include <queue> 6 #include <vector> 7 #include <algorithm> 8 9 #define rep(i,a,n) for(int i = a;i < n;i++) 10 #define per(i,n,a) for(int i = n-1;i >=a;i--) 11 #define pb push_back 12 #define VI vector<int> 13 #define QI queue<int> 14 15 typedef long long ll; 16 17 using namespace std; 18 19 const int N = 100 + 5; 20 int t; 21 double n; 22 int a[N] = {}; 23 double b[N] = {}; 24 double dp[N*100] = {}; 25 26 int main(){ 27 int T; 28 scanf("%d",&T); 29 while(T--){ 30 scanf("%lf%d",&n,&t); 31 int sum = 0; 32 rep(i,0,t){ 33 scanf("%d%lf",&a[i],&b[i]); 34 sum += a[i]; 35 } 36 memset(dp,0,sizeof(dp)); 37 dp[0] = 1; 38 rep(i,0,t+1){ 39 per(j,sum+1,a[i-1]){ 40 dp[j] = max(dp[j],dp[j - a[i-1]]*(1-b[i-1])); 41 } 42 } 43 per(i,sum+1,0){ 44 if((1-n) <= dp[i]){ 45 cout<<i<<endl; 46 break; 47 } 48 } 49 } 50 return 0; 51 }
HDU 2456
http://acm.hdu.edu.cn/showproblem.php?pid=2546
关键在于要把最贵的东西留到最后买,买到快只剩下5块的时候,再买最贵的直接刷爆
真是的这么邪恶的想法对于纯洁的我来说真的太污了!
超详细题解:http://blog.csdn.net/mengxiang000000/article/details/50365081
1 #include <cstdio> 2 #include <iostream> 3 #include <cmath> 4 #include <cstring> 5 #include <queue> 6 #include <vector> 7 #include <algorithm> 8 9 #define rep(i,a,n) for(int i = a;i < n;i++) 10 #define per(i,n,a) for(int i = n-1;i >=a;i--) 11 #define pb push_back 12 #define VI vector<int> 13 #define QI queue<int> 14 15 typedef long long ll; 16 17 using namespace std; 18 19 const int N = 1000 + 5; 20 int n,m; 21 int a[N] = {}; 22 int dp[50000 + 5] = {}; 23 24 bool cmp(int a,int b){ 25 return a < b; 26 } 27 28 int main(){ 29 while(~scanf("%d",&n),n>0){ 30 int sum = 0; 31 rep(i,0,n){ 32 scanf("%d",&a[i]); 33 sum += a[i]; 34 } 35 sort(a,a+n,cmp); 36 37 scanf("%d",&m); 38 if(m < 5){ 39 printf("%d\n",m); 40 continue; 41 } 42 memset(dp,0,sizeof(dp)); 43 rep(i,0,n){ 44 per(j,m+1-5,a[i-1]){ 45 dp[j] = max(dp[j],dp[j - a[i-1]] + a[i-1]); 46 } 47 } 48 printf("%d\n",m-dp[m-5]-a[n-1]); 49 } 50 return 0; 51 }
这些就是最近做的背包问题啦~下面就要(被)尿 并查集&最小生成树,区间dp就留在后面再来巩固一下。然后估计过完年,准备准备邻接表和哈希表差不多了。
背包问题链接:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=103972#overview
以上。