反转问题
来源:互联网 发布:网络维护外包合同 编辑:程序博客网 时间:2024/06/05 14:08
反转问题
poj3276
题意:
N头牛排成一列,每头牛或者朝前,或者朝后。为了让所有牛都面向前方,农夫约翰买了一台自动转向的机器。这个机器在购买时就必须设定一个数值K,机器每操作一次恰好使K头连续的扭转向。请求出为了让所有的牛都能面向前方所需要的最少操作次数M和对应的最小K。
限制条件:
1<=N<=5000
思路:
首先,可以确定翻转顺序对结果是没有影响的。其次,可以知道对同一个区间进行两次以上的反转是多余的。因此,我们可以从最左边开始,如果最左边那个需要反转就反转K头连续的牛,在判断第二个是否需要反转…..,这样写的话,复杂度有点高,最差o(n^3)不能解决这个问题。区间反转部分还算很容易优化的。
f[i]:=区间[i,u+K-1] 进行了反转的话就为1,否则为0
这样在考虑第i头牛时,如果
i−1
∑ f [ j] 为奇数的话,则着头牛的方向玉开始方向是相反的(就是看他之前被反转了多少次)。否则方向不
j=i−K+1
变。
由于:
∑(j=(i+1)-K+1,i) f[j] = ∑(j=i-K+1,i-1)f[j] + f[i] - f[i-K+1]
所以这个和每一次都可以在常熟时间内计算出来,复杂度就降为O(N^2)
AC代码:
//// Created by luozujian on 17-12-2.//#include<cstdio>#include<cstring>#include<algorithm>#include<iostream>#include<queue>#include<vector>using namespace std;const int maxn = 5000+5;int dir[maxn]; //牛的方向(0:F,1:B)int f[maxn]; //区间[i,i-k+1]是否进行反转int n;//固定k 求最小的操作数 无解返回-1int calc(int k){ memset(f,0,sizeof(f)); int res = 0; int sum = 0; for(int i=0;i+k<=n;i++) { if((sum+dir[i])%2 !=0) { //牛面朝后方。 f[i] = 1; res++; } sum+=f[i]; if(i-k+1 >= 0) { sum-=f[i-k+1]; } } //检查剩下的牛是否有面朝后方的情况 for(int i=n-k+1;i<n;i++) { if((sum+dir[i])%2 !=0) { return -1; //无解 } if(i-k+1>=0) { sum-=f[i-k+1]; } } return res;}void solve(){ int K = 1,M = n; for(int k=1;k<=n;k++) { int m = calc(k); if(m>0 && M>m) { K = k; M = m; } } printf("%d %d\n",K,M);}int main(){ scanf("%d",&n); for(int i=0;i<n;i++) { char str[2]; scanf("%s",str); printf("%c\n",str[0]); if(str[0] == 'B') dir[i] = 1; else dir[i] = 0; } solve(); return 0;}
阅读全文
0 0
- 反转问题
- 反转问题
- 优先级反转问题
- 字符串反转系列问题
- 数据库行列反转问题
- RTOS优先权反转问题
- hibernate反转问题
- 优先级反转问题
- 单词反转问题
- 优先级反转问题
- 反转问题--poj1222
- 单链表的反转问题
- 字符串反转问题
- 字符串反转系列问题
- 反转问题1
- 数字反转问题
- 字符串反转问题
- POJ 3276 反转问题
- HDOJ2140 Michael Scofield's letter
- ssm整合笔记
- 【Scikit-Learn 中文文档】模型评估: 量化预测的质量
- CRC原理详解(附crc16校验代码)
- 7.jquery-ajax的使用
- 反转问题
- 搭建SSM常用配置jdbc.properties
- ViewPager加载fragment
- create-react-app结合node express框架搭建react项目开发环境
- 整理MAC下Eclipse的常用快捷键
- Linux查看内存命令及其对命令显示的解释
- 剑指offer---重建二叉树
- MySQL(二)BinLog恢复数据
- TCP send函数 阻塞发送数据详解