1.尺取法
POJ 3061
#include
#include
#include
#define Max_N 50010
using namespace std;
int n, S;
int a[Max_N];
int ans[Max_N];
int ansNum = 0;
void solve() {
if (S == 0) {
ans[ansNum++] = 1;
return;
}
int res = n + 1;
int s = 0, t = 0, sum = 0;
for (;;) {
while (t < n&&sum < S)
{
sum += a[t++];
}
if (sum < S)
break;
res = min(res, t-s);
sum -= a[s++];
}
if (res > n)
res = 0;
ans[ansNum++] = res;
}
int main()
{
int cases;
cin >> cases;
while (cases>0)
{
cases--;
cin>> n >> S;
memset(a, 0, n);
for (int i = 0; i < n; ++i) {
cin >> a[i];
}
solve();
}
for (int i = 0; i < ansNum; i++) {
cout << ans[i] << endl;
}
return 0;
}
POJ3320
#include
#include
#include
POJ 2739
#include "stdafx.h"
#pragma warning(disable:4996)
#include
#include
#include
#define Max_N 100000
using namespace std;
int n;
int ans[Max_N];
int ansNum = 0;
int prime[Max_N];
bool is_Prime[Max_N];
void calculate_primes() {
int p = 0;
for (int i = 2; i < 10000; ++i) {
is_Prime[i] = true;
}
is_Prime[0] = is_Prime[1] = false;
for (int i = 2; i <= 10000; ++i) {
if (is_Prime[i])
{
prime[p++] = i;
for (int k = i * 2; k <= 10000; k += i) {
is_Prime[k] = false;
}
}
}
}
void solve() {
int number = 0;
int s = 0, t = 0, sum = 0;
int end = 0;
for (; n >= prime[end]; end++) {}
for (int i = 0; i < end; i++) {
while (sum < n&&t < end) {
sum += prime[t++];
}
if (sum < n) {
break;
}
while (sum > n&&s < t) {
sum -= prime[s++];
}
if (sum == n) {
number++;
sum -= prime[s++];
}
}
ans[ansNum++] = number;
}
int main()
{
calculate_primes();
while (scanf("%d",&n))
{
if (n == 0) {
break;
}
solve();
}
for (int i = 0; i < ansNum; i++)
{
cout << ans[i] << endl;
}
return 0;
}
2.反转问题
POJ 3276
#include
#include
#include
#define MAX_N 5050
using namespace std;
int N;
string Flip;
int dir[MAX_N];//牛的方向,0为正向,1为反向
int f[MAX_N];//区间[i,i+k-1]是否进行反转
//固定K,求对应最小操作数
//无解的话返回-1
int calc(int K) {
memset(f, 0, sizeof(f));
int res = 0;//操作数
int sum = 0;//在这头牛上操作数的和,若为奇数,则此牛的方向与初始方向相反
for (int i = 0; i + K <= N; ++i) {
//计算区间i,i+K-1
if ((dir[i] + sum) % 2 != 0) {
res++;
//即前端的牛面朝后方
f[i] = 1;//进行一次反转
}
sum += f[i];
if (i - K + 1 >= 0) {
sum -= f[i - K + 1];
}
}
//检查后面的是否有向后的情况,如果有,则无解,返回-1
for (int i = N - K + 1; i < N; ++i) {
if ((dir[i] + sum) % 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) {
M = m;
K = k;
}
}
cout << K << " " << M << endl;
}
int main()
{
char input;
cin >> N;
for (int i = 0; i < N; ++i) {
cin >> input;
if (input == 'F')
dir[i] = 0;
else
dir[i] = 1;
}
solve();
return 0;
}
集合的整数表示
空集--0
只有第i个元素的集合{i}--1< 含有全部n个元素的集合{0,1,.....,n-1}--(1<
向集合中加入第i个元素--S|1< 从集合中去除第i个元素--S&~(1< 集合S和T的并集--S|T
集合S和T的交集--S&T
3.相遇碰撞问题
POJ 3684
#include
#include "math.h"
#include
#include
#include
#define MAX_N 200
using namespace std;
const double g = 10.0;//重力加速度
int N, H, R, T;
double y[MAX_N];
double calc(int T) {
if (T < 0)
return H;
double t = sqrt(2 * H / g);
int k = (int)(T / t);
if (k % 2 == 0) {
double d = T - k * t;
return H - g * d*d / 2;
}
else {
double d = k * t + t - T;
return H - g * d*d / 2;
}
}
void solve() {
memset(y, 0, sizeof(y));
for (int i = 0; i < N; ++i) {
y[i] = calc(T - i);
}
sort(y, y + N);
for (int i = 0; i < N; ++i) {
cout <> num;
for (int i = 0; i < num; i++) {
cin >> N >> H >> R >> T;
solve();
}
return 0;
}
类似的如蚂蚁相遇,由于相遇前速度相同,相遇后两者速度不变,方向相反,可以看作没有碰撞,两个球可以看作相互穿过。