http://acm.zcmu.edu.cn/JudgeOnline/contest.php?cid=1087
A dp
类似问题:
动态规划专题,留坑待填
最大子矩阵和
...
给定一个矩阵,可以向右走,向上走,向下走但不能向左走,求从左上角走到右下角的最大值
dp[i][j][left]=max(dp[i][j-1][left],dp[i][j-1][up],dp[i][j-1][down])+a[i][j];
从上面进入的话要考虑点(i-1,j)的情况,注意不能走两次
dp[i][j][up]=max(dp[i-1][j][up],dp[i-1][j][left])+a[i][j];
从下面进入的话要考虑点(i+1,j)的情况,注意不能走两次
dp[i][j][down]=max(dp[i+1][j][down],dp[i+1][j][left])+a[i][j];
#include<iostream> #include<cstdio> #include<cstring> using namespace std; #define ll long long #define rep(i,n) for(int i=0;i<n;i++) #define per(i,n) for(int i=n-1;i>=0;i--) #define rep2(i,n) for(int i=1;i<=n;i++) #define per2(i,n) for(int i=n;i>=1;i--) int max(int a,int b,int c){return max(max(a,b),c);} int min(int a,int b,int c){return min(min(a,b),c);} int getint() { int ret=0;bool ok=0,neg=0; for(;;) { int c=getchar(); if(c>='0'&&c<='9')ret=(ret<<3)+ret+ret+c-'0',ok=1; else if(ok)return neg?-ret:ret; else if(c=='-')neg=1; } } //--------IO-------- #define up 0 #define down 1 #define left 2 int n,m; int a[110][110]; void slove() { int dp[110][110][3]; rep(i,n+2)rep(j,n+2)rep(k,3)dp[i][j][k]=-999999999; dp[0][1][up]=0; rep2(j,m) { rep2(i,n){ dp[i][j][left]=max(dp[i][j-1][left],dp[i][j-1][up],dp[i][j-1][down])+a[i][j]; } rep2(i,n){ dp[i][j][up]=max(dp[i-1][j][up],dp[i-1][j][left])+a[i][j]; } per2(i,n){ dp[i][j][down]=max(dp[i+1][j][down],dp[i+1][j][left])+a[i][j]; } } printf("%d\n",max(dp[n][m][left],dp[n][m][up],dp[n][m][down])); } int main() { int T; scanf("%d",&T); while(T--) { n=getint(),m=getint(); rep2(i,n)rep2(j,m)a[i][j]=getint(); slove(); } return 0; }
AA 水,最小表示法
有3中情况
(1). s[p1+k] > s[p2+k],则p1滑动到p1+k+1处 --- 即s1[p1->p1+k]不会是该循环字符串的“最小表示”的前缀。
(2). s[p1+k] < s[p2+k],则p2滑动到p2+k+1处,原因同上。
(3). s[p1+k] = s[p2+k],则 k++; if (k == len) 返回结果。
注:这里滑动方式有个小细节,若滑动后p1 == p2,将正在变化的那个指针再+1。直到p1、p2把整个字符串都检验完毕,返回两者中小于 len 的值。
最小表示法 zoj1729
http://www.cnblogs.com/wuyiqi/archive/2012/03/17/2403927.html
#include<iostream> #include<cstdio> #include<cstring> using namespace std; char s[100010]; void slove() { int i=0,j=1,k=0; int len=strlen(s); while(i<len&&j<len&&k<len) { int tmp=s[(i+k)%len]-s[(j+k)%len]; if(tmp==0) k++; else { if(tmp>0)i=i+k+1;//i~i+k 都不可能是最小前缀 else j=j+k+1; if(i==j)j++; k=0; } } printf("%d\n",i<j?i:j); } int main() { int T; scanf("%d",&T); while(T--) { scanf("%s",s); slove(); } return 0; }
AAA 状压dp zoj3777
用dfs的话时间复杂度为12!,大约4亿,肯定超时
dp[i][j]表示取i的二进制位为1的值兴趣值为j时的个数。
(当i&(1<<(j-1))==0)dp[i|(1<<(j-1))][k+a[tmp+1][j]] += dp[i][k]; 01背包

#include<cstdio> #include<cstring> #include<iostream> int dp[4500][550];//1<<12 int a[20][20]; int n,m; int main() { int T; scanf("%d",&T); while(T--) { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) scanf("%d",&a[i][j]); } memset(dp,0,sizeof(dp)); dp[0][0]=1; int ALL=1<<n; for(int i=0;i<ALL-1;i++) { int sloved=0; for(int j=1;j<=n;j++)//计算i中1的个数 { if(i&(1<<(j-1)))sloved++; } for(int j=1;j<=n;j++) { if(i&(1<<(j-1)))continue;//检查j列是否被占用 for(int k=0;k<=m;k++) { //>=m的情况数目都放在m里面 if(k+a[sloved+1][j]>=m)dp[i|(1<<(j-1))][m]+=dp[i][k]; else dp[i|(1<<(j-1))][k+a[sloved+1][j]]+=dp[i][k]; } } } if(dp[(1<<n)-1][m])printf("%d\n",dp[(1<<n)-1][m]); else puts("No solution"); } return 0; }
用dfs超时的代码
#include<iostream> #include<cstdio> #include<cstring> #include<iostream> using namespace std; int mp[20][20]; bool vis[20]; int n,m; int cnt; int getint() { int ret=0;bool ok=0,neg=0; for(;;) { int c=getchar(); if(c>='0'&&c<='9')ret=(ret<<3)+ret+ret+c-'0',ok=1; else if(ok)return neg?-ret:ret; else if(c=='-')neg=1; } } void dfs(int k,int sum) { // printf("%d %d\n",k,sum); if(k==n) { if(sum>=m)cnt++; return; } for(int i=0;i<n;i++) { if(!vis[i]) { vis[i]=true; dfs(k+1,sum+mp[k][i]); vis[i]=false; } } } int main() { int T; T=getint(); while(T--) { n=getint(),m=getint(); memset(vis,false,sizeof(vis)); for(int i=0;i<n;i++) { for(int j=0;j<n;j++)mp[i][j]=getint(); } cnt=0; dfs(0,0); if(cnt)printf("%d\n",cnt); else puts("No solution"); } return 0; }
AAAA 水 用递归画图
#include<iostream> #include<cstdio> using namespace std; char s[800][800]; int val[10]; void dfs(int x,int y,int level) { if(level==1){ s[x][y]='+'; return; } int d=val[level-1]; dfs(x,y,level-1); dfs(x-d,y,level-1); dfs(x+d,y,level-1); dfs(x,y-d,level-1); dfs(x,y+d,level-1); } int main() { int n; val[1]=1; for(int i=2;i<8;i++)val[i]=val[i-1]*3; int flag=1; while(~scanf("%d",&n)) { if(flag)flag=0; else puts(""); for(int i=0;i<800;i++) { for(int j=0;j<800;j++)s[i][j]=' '; } dfs(val[n]/2,val[n]/2,n); for(int i=0;i<val[n];i++) { for(int j=val[n]-1;j>=0;j--) { if(s[i][j]!=' ') { s[i][j+1]='\0'; break; } } puts(s[i]); } } return 0; }
AAAAA 水,模拟
浮点数补0 printf("%05.2f",5.2);
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; char str[110]; struct ss { int val; char str[110]; }a[10010]; int num=0; bool cmp(ss a, ss b) { return a.val<b.val; } int gettime(char *s,int l,int r) { int mm=0,ss=0,ff=0,i=l; while(i<=r&&s[i]!=':')mm=mm*10+s[i++]-'0'; i++; while(i<=r&&s[i]!='.')ss=ss*10+s[i++]-'0'; i++; while(i<=r)ff=ff*10+s[i++]-'0'; return mm*10000+ss*100+ff; } int main() { // freopen("tes.in","r",stdin); while(gets(str)) { int len=strlen(str); int pstr; for(int i=len-1;i>=0;i--) { if(str[i]==']'){ pstr=i; break; } } char s[110]; int pp=0; for(int i=pstr+1;i<len;i++)s[pp++]=str[i]; s[pp]='\0'; int i=0; while(i<=pstr) { int l,r; while(i<=pstr&&str[i]!='[')i++; l=i+1; while(i<=pstr&&str[i]!=']')i++; r=i-1; if(l>r)break; int t=gettime(str,l,r); a[num].val=t; strcpy(a[num].str,s); num++; } } sort(a,a+num,cmp); for(int i=0;i<num;i++)printf("[%02d:%02d.%02d]%s\n",a[i].val/10000,a[i].val%10000/100,a[i].val%100,a[i].str); return 0; }
浙公网安备 33010602011771号