poj 3276(反转)

传送门:Problem 3276

参考资料:

  [1]:挑战程序设计竞赛

先献上AC代码,题解晚上再补

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 using namespace std;
 5 #define mem(a,b) (memset(a,b,sizeof(a)))
 6 const int maxn=5e3+30;
 7
 8 int N;
 9 int dir[maxn];//0:forward; 1:backward
10 int f[maxn];
11
12 int Calculate(int k)
13 {
14     mem(f,0);
15     int res=0;
16     int sum=0;
17     for(int i=1;i+k-1 <= N;++i)
18     {
19         if(i-k > 0)//如果在 i-k 处使用机器,作用的范围为 [i-k,i-1] ,共 k 头牛,所以需要在第 i 处减去在 i-k 处的反转次数
20             sum -= f[i-k];
21         if((dir[i]+sum)%2 != 0)
22             res++,f[i]=1;
23         sum += f[i];
24     }
25     for(int i=N-k+2;i <= N;++i)
26     {
27         if(i-k > 0)//同上解释
28             sum -= f[i-k];
29         if((dir[i]+sum)%2 != 0)
30             return -1;
31     }
32     return res;
33 }
34 void Solve()
35 {
36     int K=1,M=N;
37     for(int k=1;k <= N;++k)//每次反转 k 头牛
38     {
39         int m=Calculate(k);
40         if(m != -1 && m < N)
41             K=k,M=m;
42     }
43     printf("%d %d\n",K,M);
44 }
45
46 int main()
47 {
48     scanf("%d",&N);
49     for(int i=1;i <= N;++i)
50     {
51         getchar();
52         char c;
53         c=getchar();
54         dir[i]=(c == ‘F‘ ? 0:1);
55     }
56     Solve();
57 }

原文地址:https://www.cnblogs.com/violet-acmer/p/9802218.html

时间: 2024-10-28 08:02:12

poj 3276(反转)的相关文章

POJ 3276 反转问题

#include <cstdio> #include <iostream> #include <cstring> using namespace std; int n; int a[5005][2]; int flag[5005]; int fun(int x){ int sum = 0; int res = 0; memset(flag,0,sizeof(flag)); for(int i = 0;i+x <= n;i++){ if(sum%2 == 0 &am

Face The Right Way POJ 3276(反转)

原题 题目链接 题目分析 由题意可以知道,对于特定的k,同一个区间反转两次是无意义的,考虑能翻第一头牛的区间只有第一个区间,因此第一头牛直接决定是否要翻转第一个区间,然后问题规模减1,同理再对第二头牛进行同样的分析.这里的翻转操作可以用前缀和优化,设f[i]=1表示以第i头牛开始的区间被翻过,f[i]=0则表示没被翻过,则考虑第j头牛时,只需统计前k-1头牛的f值,如果和是奇数则表明第j头牛的朝向与原方向相反,否则相同,最后就可以用O(N)的复杂求求解一个k的最小步骤m,由于所有k都要试一遍,最

反转(开关问题) POJ 3276

POJ 3276 题意:n头牛站成线,有朝前有朝后的的,然后每次可以选择大小为k的区间里的牛全部转向,会有一个最小操作m次使得它们全部面朝前方.问:求最小操作m,再此基础上求k. 题解:1.5000头牛不是小数目,再怎么也得要n^2的算法,其中,枚举k是需要的,这就有n了,只能想办法给出一个n在O(n)时间内求出最小次数了. 2.对于给定的k,要想O(n)内把次数算出来,即只能扫一遍,一想到的必定是从前往后扫,遇到面朝后的就转头,但这一转牵扯太多,要改太多东西,k一大直接崩溃. 3.对于每次扫描

POJ 3276 Face The Right Way (常用技巧-尺取法)

[题目链接]:click here~~ [题目大意]:N头牛排成一列1<=N<=5000.每头牛或者向前或者向后.为了让所有牛都 面向前方,农夫每次可以将K头连续的牛转向1<=K<=N,求操作的最少 次数M和对应的最小K. [思路]:由于交换区间翻转顺序对结果没影响,所以从左往右对于需要  翻转的牛进行反转,同时记录对该区间其他牛的影响即cal中的sum, 对于最后部分无法翻转的区间检查是否有反向牛,若有则方案失败.此题思想值得细细思考,常常有一种无限状态,化为有限状态. 代码:

POJ 3276 [Face The Right Way] 题解

题目大意 n头牛排成一行,有的牛面朝前,有的牛面朝后,每一次操作可以使连续的K头牛改变方向:求一个K,使得操作次数最少.输出K以及最少的操作次数.当有多个K满足条件时,输出最小的K. 题目分析 对一个区间来说,多次进行反转操作是没有意义的:另外反转的顺序对结果是没有影响的.所以这道题只需要对所有的可操作区间(即长度为K的区间)考虑是否需要反转. 考虑最左边的牛,当它面朝前时无需反转,当它面朝后时,就反转[1, K]区间一次.然后继续考虑第二头牛即可. 反转的时候不必每头牛都操作一次,只需用一个t

POJ 3276 Face The Right Way 开关问题

Face The Right Way Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 4367   Accepted: 2025 Description Farmer John has arranged his N (1 ≤ N ≤ 5,000) cows in a row and many of them are facing forward, like good cows. Some of them are facin

POJ 3276 (开关问题)

题目链接: http://poj.org/problem?id=3276 题目大意:有一些牛,头要么朝前要么朝后,现在要求确定一个连续反转牛头的区间K,使得所有牛都朝前,且反转次数m尽可能小. 解题思路: 首先不要看错题意了,不是求最小K,不要二分.而且反转区间长度一定是K,小于K是不能反转的. 很明显得枚举K(1...n),并且有以下反转思路: ①从第一头牛开始,如果朝前,不管了.看下一头牛,如果朝后反转K长度区间.....一直扫到区间结束. ②第一趟结束后,如果不符合要求,继续重复①,直到所

poj 3276 Face The Right Way 递推

地址  http://poj.org/problem?id=3276 解法 依次遍历一次翻转K(1~N)头牛的办法 最后得出转数最小的答案  复杂度是 N*N*N 但是在模拟一次翻转K头牛的时候 我们可以优化模拟翻转的过程 优化效率 如图 当K = 3 每次翻转3头牛的时候 第0头牛 朝后 之前影响到第0头牛的点击数为0 所以我们需要点击1次 将牛朝前 第1头牛 朝后 之前影响第1头牛的点击数为1 所以牛已经朝前不必点击 第2头牛 朝前 之前影响第2头牛的点击数为1 所以需要点击1次  将牛朝前

poj 3276

开关反转问题,想法很巧妙,看了一节课才看懂,严重怀疑自己弱智....就难受 #include <iostream> #include <cstring> #include <algorithm> #include <cstdio> using namespace std; const int maxn=5000+10; int a[maxn],f[maxn];//B:1,F:0 int n; int fan(int k) { int sum=0,ans=0;