假期训练五(poj-1077bfs+康拓展开,hdu-2577dp)
题目一:传送门
思路:主要是找到状态,
考虑字母有两种状态,大写和小写,
从小写变为大写的变化方式有两种:保持cap状态,或者按住shift键;
从小写变为大写也有一种变化方式:按住shift键;
看起来很乱,但是主要就是是否为cap状态,shift可以看做多按一次键,
不能算作状态,所以一个字母就两个状态,大写键开启,或不开启。
由此建立一个二维数组dp[i][j],i表示节点位置;j表示状态,有0,1两种,表示大写键开启或不开启。
然后就是从0--len依次循环更新状态就行了,注意最终状态是大写键关闭。
代码:
#include<iostream> #include<cstdio> #include<cstring> using namespace std; const int maxn = 120; const int INF = 9999999; char str[maxn]; int dp[maxn][5],a[maxn]; int MIN(int x,int y) { return x<y?x:y; } int main(void) { int t,fg,i,len,cnt,j; scanf("%d",&t); while(t--) { scanf("%s",str); len=strlen(str); dp[0][0]=0,dp[0][1]=1; for(i=0;i<len;i++) { if(str[i]>='a'&&str[i]<='z') { dp[i+1][0]=MIN(dp[i][0]+1,dp[i][1]+2); dp[i+1][1]=MIN(dp[i][0]+2,dp[i][1]+2); } else { dp[i+1][0]=MIN(dp[i][0]+2,dp[i][1]+2); dp[i+1][1]=MIN(dp[i][0]+2,dp[i][1]+1); } } printf("%d\n",MIN(dp[len][1]+1,dp[len][0])); } return 0; }
题目二:传送门
思路:bfs+康托展开
参考文章:传送门
(1)将二维坐标用以为数组存储,每次只要进行行列变换就行了;
(2)每次交换两个坐标的值,然后再重新算出这个序列在全排列中的位置;
(3)x可以设为9,利用康拓展开每次返回当前序列在1-9全排列的位置,截止的标志是statu==1;
(4)每次记录变换的方向和前一个位置。