博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
2012 Multi-University Training Contest 8
阅读量:4313 次
发布时间:2019-06-06

本文共 6008 字,大约阅读时间需要 20 分钟。

官方解题报告:

1001 hdu 4370 

题意:

给你一个n*n的矩阵,求另一个矩阵满足如下条件:

1.X12+X13+...X1n=1

2.X1n+X2n+...Xn-1n=1
3.for each i (1<i<n), satisfies ∑Xki (1<=k<=n)=∑Xij (1<=j<=n).

使得∑Cij*Xij(1<=i,j<=n) 最小,官方解题报告已经很完善这里不再罗嗦,只是强调一下在自己出现的错误:

1:这里分别得到由1,n出发的环视如果不存在返回的都是inf如果令inf = 0x7fffffff或者0x7f7f7f7f时,相加会查数据范围,这里要给出最大值为2^29

2:这里由1,n出发得到的环必须至少经过一个点,因为条件1,2应经限制了。

View Code
#include 
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define CL(a,num) memset((a),(num),sizeof(a))#define iabs(x) ((x) > 0 ? (x) : -(x))#define maxn 307#define ll __int64#define inf 536870912#define MOD 100000007using namespace std;int mat[maxn][maxn],dis[maxn];bool vt[maxn];int n,m;int SPFA(int s){ int i; CL(vt,false); queue
q; while (!q.empty()) q.pop(); for (i = 1; i <= n; ++i) { dis[i] = inf; } dis[s] = 0; vt[s] = true; q.push(s); int cir = inf; while (!q.empty()) { int u = q.front(); q.pop(); for (i = 1; i <= n; ++i) { if (dis[i] > dis[u] + mat[u][i]) { dis[i] = dis[u] + mat[u][i]; if (!vt[i]) { vt[i] = true; q.push(i); } } if (i == u) continue;//这里控制由1,n出发得到的环必须至少经过一个点 if (i == s && cir > dis[u] + mat[u][i]) { cir = dis[u] + mat[u][i]; } } vt[u] = false; } return cir;}int main(){ //freopen("din.txt","r",stdin); int i,j; while (~scanf("%d",&n)) { for (i = 1; i <= n; ++i) for (j = 1; j <= n; ++j) scanf("%d",&mat[i][j]); int c2 = SPFA(1);//由1出发得到的环 int c1 = dis[n]; int c3 = SPFA(n);//由n出发得到的环 printf("%d\n",min(c2 + c3,c1)); } return 0;}

 

1005hdu 4374  

题意:

有一个n曾的楼,从第一层往上走,每一层都有m块,可以从对应的本层的第y块跳到上一层的第y块,要求限制每一层只能往左右走,而且走的最大长度为T,问到达第n才层后的最大得分(ps:这里每一块都对应着一个得分,给出n*m举证表示得分);

思路:

这里简单的dp O(n*m*m)肯定会超时,所以这里要用单调队列来优化,这道题目和上次比赛的1003一样都是用单调队列来优化的。

View Code
#include 
#include
#include
#include
#include
#include
#include
#include
#include
#define CL(a,num) memset((a),(num),sizeof(a))#define iabs(x) ((x) > 0 ? (x) : -(x))#define N 107#define M 10007#define inf 0x7f7f7f7fusing namespace std;int dp[N][M],sum[N][M],map[N][M];int q[M*2];int n,m,X,T;int main(){ //freopen("din.txt","r",stdin); int i,j; while (~scanf("%d%d%d%d",&n,&m,&X,&T)) { CL(sum,0); for (i = 1; i <= n; ++i) { for (j = 1; j <= m; ++j) { scanf("%d",&map[i][j]); sum[i][j] = sum[i][j - 1] + map[i][j]; dp[i][j] = -inf; } } dp[1][X] = map[1][X]; for (j = X + 1; j <= m && j - X <= T; ++j) dp[1][j] = dp[1][j - 1] + map[1][j]; for (j = X - 1; j >= 1 && X - j <= T; --j) dp[1][j] = dp[1][j + 1] + map[1][j]; int front,tail; for (i = 2; i <= n; ++i) { front = 0,tail = -1; //左扫 for (j = 1; j <= m; ++j) { while (tail >= front && j - q[front] > T) front++;//保持对头满足小于T if(dp[i - 1][j] != -inf)//因为得分由负值,所以要限制一下 { int tmp = dp[i - 1][j] + map[i][j]; while (tail >= front && tmp > dp[i - 1][q[tail]] + sum[i][j] - sum[i][q[tail] - 1]) tail--; q[++tail] = j; } if (tail >= front) dp[i][j] = max(dp[i][j],dp[i - 1][q[front]] + sum[i][j] - sum[i][q[front] - 1]); } //右扫 front = 0,tail = -1; for (j = m; j >= 1; --j) { while (tail >= front && q[front] - j > T) front++; if(dp[i - 1][j] != -inf) { int tmp = dp[i - 1][j] + map[i][j]; while (tail >= front && tmp > dp[i - 1][q[tail]] + sum[i][q[tail]] - sum[i][j - 1]) tail--; q[++tail] = j; } if (tail >= front) dp[i][j] = max(dp[i][j],dp[i - 1][q[front]] + sum[i][q[front]] - sum[i][j - 1]); } } int MAX = -inf; for (i = 1; i <= m; ++i) { MAX = max(MAX,dp[n][i]); } printf("%d\n",MAX); } return 0;}

1008 hdu 4377 

题意:

定义:U(A) 为序列A的最长上升子序列,D(A)为序列A的最长下降子序列,H(A) = max{U(A), D(A)}  求1-n的全排列里面所有序列的的H(A)的最小值。

思路:参考官方解题报告

举例10 -- 16 他们的sqrt()都为4 而10到12 都是分出三段,13到16 都是分出四段,我们按长度为4= sqrt(n)来分的,他的最长下降子序列已经确定为4,而最长上升子序列不能超过m所以对于分出三段的来说只要他的最前边的一段取出1个或者2个即可,又因为我们呢要保证字典序最小,所以我们把1放在最前边剩余逆序即可,而对于分出四段的我们必须从前边取出一个故必须降序。

View Code
#include 
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define CL(a,num) memset((a),(num),sizeof(a))#define iabs(x) ((x) > 0 ? (x) : -(x))#define maxn 100007#define ll __int64#define inf 0x7f7f7f7f#define MOD 100000007using namespace std;int ans[maxn];int main(){ //freopen("din.txt","r",stdin); int t,i; int n,m,len; scanf("%d",&t); while (t--) { len = 0; int s,e; scanf("%d",&n); m = ceil(sqrt(1.0*n)); s = 1; if (m*(m - 1) >= n)//判断是否分出m-1段 { ans[len++] = 1;//保证字典序最小 s++; } //其余逆序 e = (n - 1)%m + 1; for (i = e; i >= s; --i) ans[len++] = i; s = e + 1; int tmp = m - 1; while (s + tmp <= n) { e = s + tmp; for (i = e; i >= s; --i) ans[len++] = i; s = e + 1; } for (i = 0; i < len - 1; ++i) printf("%d ",ans[i]); printf("%d\n",ans[i]); } return 0;}

1010 hdu 4379 

题意:

序列{X1, X2, ... , Xn}由 Xk = (A * k + B) % mod产生,在序列{X1, X2, ... , Xn}中选一个子序列 {Y1, Y2, ... , Ym}是盖子序列满足:

 Yi + Yj <= L (1 ≤ i < j ≤ m), and every Yi <= L (1 ≤ i ≤ m ) 求最长的m

这道题目最坑爹了,卡数据类型,思路参考官方解题报告:

View Code
#include 
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define CL(a,num) memset((a),(num),sizeof(a))#define iabs(x) ((x) > 0 ? (x) : -(x))#define maxn 107#define ll __int64#define inf 0x7fffffff#define MOD 1000007#define N 1000007#define M 30000#define lc l,m,rt<<1#define rc m + 1,r,rt<<1|1using namespace std;int main(){ //freopen("din.txt","r",stdin); int i; ll A,B,L,n,mod; // printf("%d\n",inf); while (scanf("%I64d%I64d%I64d%I64d%I64d",&n,&L,&A,&B,&mod) != EOF) { int mid = L/2; int cnt = 0; ll MIN = 1; MIN <<= 62; ll MAX = 0; for (i = 1; i <= n; ++i) { ll tmp = (A*i + B)%mod; if (tmp <= mid) { cnt++; if (MAX < tmp) MAX = tmp; } else { if (MIN > tmp) MIN = tmp; } } if (MIN + MAX <= L) cnt++; printf("%d\n",cnt); } return 0;}

 

 

转载于:https://www.cnblogs.com/E-star/archive/2012/08/20/2648113.html

你可能感兴趣的文章
win64 Python下安装PIL出错解决2.7版本 (3.6版本可以使用)
查看>>
获取各种类型的节点
查看>>
表达式求值-201308081712.txt
查看>>
centos中安装tomcat6
查看>>
从Vue.js窥探前端行业
查看>>
学习进度
查看>>
poj3368 RMQ
查看>>
“此人不存在”
查看>>
github.com加速节点
查看>>
解密zend-PHP凤凰源码程序
查看>>
python3 序列分片记录
查看>>
Atitit.git的存储结构and 追踪
查看>>
atitit 读书与获取知识资料的attilax的总结.docx
查看>>
B站 React教程笔记day2(3)React-Redux
查看>>
找了一个api管理工具
查看>>
C++——string类和标准模板库
查看>>
zt C++ list 类学习笔记
查看>>
git常用命令
查看>>
探讨和比较Java和_NET的序列化_Serialization_框架
查看>>
1、jQuery概述
查看>>