http://acm.hdu.edu.cn/listproblem.php?vol=36
1:小Q系列故事——屌丝的逆袭
思路:和省赛的那个题目类似,只要模拟一下就好...
#include <iostream> #include <cstdio> #include <cmath> #include <vector> #include <cstring> #include <algorithm> #include <string> #include <set> #include <functional> #include <numeric> #include <sstream> #include <stack> #include <map> #include <queue> #define CL(arr, val) memset(arr, val, sizeof(arr)) #define lc l,m,rt<<1 #define rc m + 1,r,rt<<1|1 #define pi acos(-1.0) #define ll long long #define L(x) (x) << 1 #define R(x) (x) << 1 | 1 #define MID(l, r) (l + r) >> 1 #define Min(x, y) (x) < (y) ? (x) : (y) #define Max(x, y) (x) < (y) ? (y) : (x) #define E(x) (1 << (x)) #define iabs(x) (x) < 0 ? -(x) : (x) #define OUT(x) printf("%I64d\n", x) #define lowbit(x) (x)&(-x) #define Read() freopen("din.txt", "r", stdin) #define Write() freopen("dout.txt", "w", stdout); #define inf 0x7f7f7f7f #define M 150 #define N 22 using namespace std; int mat[N][N]; int ans[N][N]; int n,m; int dir[4][2] = {{1,0},{-1,0},{0,1},{0,-1}}; int Abs(int x) { if (x >= 0) return x; else return (-x); } int main() { int i,j,k; while (~scanf("%d%d",&n,&m)) { if (!n && !m) break; for (i = 0; i < n; ++i) { for (j = 0; j < m; ++j) { scanf("%d",&mat[i][j]); } } CL(ans,0); for (i = 0; i < n; ++i) { for (j = 0; j < m; ++j) { for (k = 0; k < 4; ++k) { int ti = i + dir[k][0]; int tj = j + dir[k][1]; if (ti >= 0 && ti < n && tj >= 0 && tj < m) { if (mat[i][j]*mat[ti][tj] < 0) ans[i][j] += Abs(mat[ti][tj]); else ans[i][j] -= Abs(mat[ti][tj]); } } } } int res = -inf; int row = 0, col = 0; for (i = 0; i < n; ++i) { for (j = 0; j < m; ++j) { if (ans[i][j] > res) { res = ans[i][j]; row = i; col = j; } else if (ans[i][j] == res && ((row > i) || (row == i && col > j))) { res = ans[i][j]; row = i; col = j; } // printf("%d ",ans[i][j]); } // printf("\n"); } // if (res == -inf) res = 0; printf("%d %d %d\n",row + 1,col + 1,res); } return 0; }
2:小明系列故事——买年货
思路:DP ,才开始开了个三维的DP怎么调数据都不出来,后来一看不对。这样会出现重复选的可能。后来开成了四维,没有用滚动数组优化就可以过,不过时间还是很紧的。
dp[no][i][j][k] = max(dp[no][i][j][k],dp[no - 1][i - a][j][k] + val,dp[no - 1][i][j - b][k] + val,dp[no - 1][i][j][k - 1] + val,dp[no - 1][i][j][k]);
前几个还好想,就是在dp[no - 1][i][j][k]没处理好,就是对于这件物品,我可能不买。 no表示第几件物品,i表示金钱数,j表示积分,k表示可以免费领取的商品数。
//#pragma comment(linker,"/STACK:327680000,327680000") #include <iostream> #include <cstdio> #include <cmath> #include <vector> #include <cstring> #include <algorithm> #include <string> #include <set> #include <functional> #include <numeric> #include <sstream> #include <stack> #include <map> #include <queue> #define CL(arr, val) memset(arr, val, sizeof(arr)) #define lc l,m,rt<<1 #define rc m + 1,r,rt<<1|1 #define pi acos(-1.0) #define ll __int64 #define L(x) (x) << 1 #define R(x) (x) << 1 | 1 #define MID(l, r) (l + r) >> 1 #define Min(x, y) (x) < (y) ? (x) : (y) #define Max(x, y) (x) < (y) ? (y) : (x) #define E(x) (1 << (x)) #define iabs(x) (x) < 0 ? -(x) : (x) #define OUT(x) printf("%I64d\n", x) #define lowbit(x) (x)&(-x) #define Read() freopen("din.txt", "r", stdin) #define Write() freopen("dout.txt", "w", stdout); #define M 307 #define N 4100007 using namespace std; struct node { int a,b,val; }nd[107]; int dp[107][107][107][6]; int n,v1,v2,k; int DP(int no,int vi,int vj,int ki) { if (no < 0 || vi < 0 || vj < 0 || ki < 0) return -1; if (dp[no][vi][vj][ki]) return dp[no][vi][vj][ki]; int tmp; tmp = DP(no - 1,vi - nd[no].a,vj,ki); if (tmp != -1) { tmp += nd[no].val; dp[no][vi][vj][ki] = max(dp[no][vi][vj][ki],tmp); } tmp = DP(no - 1,vi,vj - nd[no].b,ki); if (tmp != -1) { tmp += nd[no].val; dp[no][vi][vj][ki] = max(dp[no][vi][vj][ki],tmp); } tmp = DP(no - 1,vi,vj,ki - 1); if (tmp != -1) { tmp += nd[no].val; dp[no][vi][vj][ki] = max(dp[no][vi][vj][ki],tmp); } tmp = DP(no - 1,vi,vj,ki); if (tmp != -1) dp[no][vi][vj][ki] = max(dp[no][vi][vj][ki],tmp); return dp[no][vi][vj][ki]; } int main() { // Read(); int i; while (~scanf("%d%d%d%d",&n,&v1,&v2,&k)) { for (i = 1; i <= n; ++i) { scanf("%d%d%d",&nd[i].a,&nd[i].b,&nd[i].val); } CL(dp,0); printf("%d\n",DP(n,v1,v2,k)); } return 0; }
优化到三维后相当于多维的01背包:
//#pragma comment(linker,"/STACK:327680000,327680000") #include <iostream> #include <cstdio> #include <cmath> #include <vector> #include <cstring> #include <algorithm> #include <string> #include <set> #include <functional> #include <numeric> #include <sstream> #include <stack> #include <map> #include <queue> #define CL(arr, val) memset(arr, val, sizeof(arr)) #define lc l,m,rt<<1 #define rc m + 1,r,rt<<1|1 #define pi acos(-1.0) #define ll __int64 #define L(x) (x) << 1 #define R(x) (x) << 1 | 1 #define MID(l, r) (l + r) >> 1 #define Min(x, y) (x) < (y) ? (x) : (y) #define Max(x, y) (x) < (y) ? (y) : (x) #define E(x) (1 << (x)) #define iabs(x) (x) < 0 ? -(x) : (x) #define OUT(x) printf("%I64d\n", x) #define lowbit(x) (x)&(-x) #define Read() freopen("din.txt", "r", stdin) #define Write() freopen("dout.txt", "w", stdout); #define M 307 #define N 4100007 using namespace std; struct node { int a,b,val; }nd[107]; int dp[107][107][6]; int n,v1,v2,k; int main() { // Read(); int i,j,ki,p; while (~scanf("%d%d%d%d",&n,&v1,&v2,&k)) { CL(dp,0); for (i = 1; i <= n; ++i) { scanf("%d%d%d",&nd[i].a,&nd[i].b,&nd[i].val); } for (p = 1; p <= n; ++p) { for (i = v1; i >= 0; --i) { for (j = v2; j >= 0; --j) { for (ki = k; ki >= 0; --ki) { int tmp = 0; if (i - nd[p].a >= 0) tmp = max(tmp,dp[i - nd[p].a][j][ki] + nd[p].val); if (j - nd[p].b >= 0) tmp = max(tmp,dp[i][j - nd[p].b][ki] + nd[p].val); if (ki - 1 >= 0) tmp = max(tmp,dp[i][j][ki - 1] + nd[p].val); dp[i][j][ki] = max(dp[i][j][ki],tmp); } } } } int ans = 0; for (i = 0; i <= v1; ++i) { for (j = 0; j <= v2; ++j) { for (ki = 0; ki <= k; ++ki) { // printf("%d\n",dp[i][j][ki]); ans = max(ans,dp[i][j][ki]); } } } printf("%d\n",ans); } return 0; }
3:吉哥系列故事——临时工计划
思路:DP ,按时间排序之后DP即可,dp[i]表示到第i个工作时,可获得最高的工资.dp[i] += max(dp[k]) k < i
#include <iostream> #include <cstdio> #include <cmath> #include <vector> #include <cstring> #include <algorithm> #include <string> #include <set> #include <functional> #include <numeric> #include <sstream> #include <stack> #include <map> #include <queue> #define CL(arr, val) memset(arr, val, sizeof(arr)) #define lc l,m,rt<<1 #define rc m + 1,r,rt<<1|1 #define pi acos(-1.0) #define ll long long #define L(x) (x) << 1 #define R(x) (x) << 1 | 1 #define MID(l, r) (l + r) >> 1 #define Min(x, y) (x) < (y) ? (x) : (y) #define Max(x, y) (x) < (y) ? (y) : (x) #define E(x) (1 << (x)) #define iabs(x) (x) < 0 ? -(x) : (x) #define OUT(x) printf("%I64d\n", x) #define lowbit(x) (x)&(-x) #define Read() freopen("din.txt", "r", stdin) #define Write() freopen("dout.txt", "w", stdout); #define inf 0x7f7f7f7f #define M 107 #define N 1007 using namespace std; struct node { int s,e; int val; }nd[N]; int m,n; int dp[N]; int cmp(node a,node b) { if (a.s != b.s) return a.s < b.s; else return a.e < b.e; } int main() { // Read(); int i,j; int T; int s,e,val; scanf("%d",&T); while (T--) { scanf("%d%d",&m,&n); int tn = 0; for (i = 1; i <= n; ++i) { scanf("%d%d%d",&s,&e,&val); if (e >= 1 && e <= m && s >= 1 && s <= m) { nd[tn].s = s; nd[tn].e = e; nd[tn++].val = val; } } sort(nd,nd + tn,cmp); // for (i = 0; i < tn; ++i) // { // printf(">>%d %d %d\n",nd[i].s,nd[i].e,nd[i].val); // } CL(dp,0); for (i = 0; i < tn; ++i) { dp[i] = nd[i].val; int tmp = 0; for (j = 0; j < i; ++j) { if (nd[j].e < nd[i].s) { tmp = max(tmp,dp[j]); } } dp[i] += tmp; } int ans = 0; for (i = 0; i < tn; ++i) { ans = max(ans,dp[i]); } printf("%d\n",ans); } return 0; }
4:湫湫系列故事——植树节
思路:直接考虑可能会比较麻烦一点,我们考虑它的反面,只要我们选的其余两个人一个是他朋友,一个不是他朋友就满足了它的对立面,则一共有C(n,3)中组和,每一个i,存在对立面的可能数为a[i]*(an - 1 - a[i])中间会出现计算两次,顾要除以2;
#include <iostream> #include <cstdio> #include <cmath> #include <vector> #include <cstring> #include <algorithm> #include <string> #include <set> #include <functional> #include <numeric> #include <sstream> #include <stack> #include <map> #include <queue> #define CL(arr, val) memset(arr, val, sizeof(arr)) #define ll __int64 #define inf 0x7f7f7f7f #define lc l,m,rt<<1 #define rc m + 1,r,rt<<1|1 #define pi acos(-1.0) #define L(x) (x) << 1 #define R(x) (x) << 1 | 1 #define MID(l, r) (l + r) >> 1 #define Min(x, y) (x) < (y) ? (x) : (y) #define Max(x, y) (x) < (y) ? (y) : (x) #define E(x) (1 << (x)) #define iabs(x) (x) < 0 ? -(x) : (x) #define OUT(x) printf("%I64d\n", x) #define lowbit(x) (x)&(-x) #define Read() freopen("din.txt", "r", stdin) #define Write() freopen("dout.txt", "w", stdout); #define N 1007 #define M 1007 const int mod = 1000000007; using namespace std; int a[N]; int main() { int i,j; int T,n; scanf("%d",&T); while (T--) { scanf("%d",&n); for (i = 0; i < n; ++i) scanf("%d",&a[i]); int ans = 0; for (i = 0; i < n; ++i) { ans += (a[i]*(n - a[i] - 1)); } double div = n*(n - 1)*(n - 2)/6; printf("%.3lf\n",1 - (1.0*ans)/(2*div)); } }
5:威威猫系列故事——篮球梦
思路:算出A要进攻多少场(m)之后,然后枚举得分分别为1,2,3的场数,就相当于吧这几场往m里面放,那么可能输为C(m,i)*C(m - i,j)*C(m - i - j,k);
#include <iostream> #include <cstdio> #include <cmath> #include <vector> #include <cstring> #include <algorithm> #include <string> #include <set> #include <functional> #include <numeric> #include <sstream> #include <stack> #include <map> #include <queue> #define CL(arr, val) memset(arr, val, sizeof(arr)) #define ll __int64 #define inf 0x7f7f7f7f #define lc l,m,rt<<1 #define rc m + 1,r,rt<<1|1 #define pi acos(-1.0) #define L(x) (x) << 1 #define R(x) (x) << 1 | 1 #define MID(l, r) (l + r) >> 1 #define Min(x, y) (x) < (y) ? (x) : (y) #define Max(x, y) (x) < (y) ? (y) : (x) #define E(x) (1 << (x)) #define iabs(x) (x) < 0 ? -(x) : (x) #define OUT(x) printf("%I64d\n", x) #define lowbit(x) (x)&(-x) #define Read() freopen("din.txt", "r", stdin) #define Write() freopen("dout.txt", "w", stdout); #define N 1007 #define M 1007 const int mod = 1000000007; using namespace std; int a[N]; int main() { int i,j; int T,n; scanf("%d",&T); while (T--) { scanf("%d",&n); for (i = 0; i < n; ++i) scanf("%d",&a[i]); int ans = 0; for (i = 0; i < n; ++i) { ans += (a[i]*(n - a[i] - 1)); } double div = n*(n - 1)*(n - 2)/6; printf("%.3lf\n",1 - (1.0*ans)/(2*div)); } }