#include<iostream>
#include<cmath>
#include <string>
#include <string.h>
#include <algorithm>
#include<cctype>
using namespace std;
int main(){
int r,n;
int sum=0;
cin>>n>>r;
int w[501],tape[76]={0};
for(int i=0;i<n;i++){
cin>>w[i];
}
sort(w,w+n);
for(int i=0;i<n;i++){
sort(tape,tape+r);
sum+=tape[0]+w[i];
tape[0]+=w[i];
}
cout<<sum;
return 0;
}
/*
ID: your_id_here
PROG: contact
LANG: C++
*/
#include <cstdio>
#include <string>
#include <map>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
struct Node {
string s;
int cnt;
Node(const string& ss="",int nn=0):s(ss),cnt(nn) {}
bool operator < (const Node& a) const {
if(cnt!=a.cnt)
return cnt>a.cnt;
if(s.size()!=a.s.size())
return s.size()<a.s.size();
return s.compare(a.s)<0;
}
};
string s,t;
map<string,int> mp;
vector<Node> ans;
int a,b,n,i,num;
int main() {
freopen("contact.in","r",stdin);
freopen("contact.out","w",stdout);
cin>>a>>b>>n>>s;
while(cin>>t)
s+=t;
while(b>=a) {
for(int i=s.size()-b;i>=0;--i) {
t=s.substr(i,b);
if(mp[t]==0)
ans.push_back(Node(t));
++mp[t];
}
--b;
}
for(i=0;i<ans.size();++i)
ans[i].cnt=mp[ans[i].s];
sort(ans.begin(),ans.end());
i=0;
while(n--) {
if(i==ans.size())
break;
cout<<ans[i].cnt<<"\n"<<ans[i].s;
num=1;
while(++i<ans.size()&&ans[i].cnt==ans[i-1].cnt) {
if(num==6) {
cout<<"\n";
num=0;
}
else
cout<<" ";
cout<<ans[i].s;
++num;
}
cout<<"\n";
}
return 0;
}
#include <bits/stdc++.h>
using namespace std;
int main() {
int len;
string s;
cin >> len >> s;
map<char, int> chNum;
//统计各个字符出现次数
for(int i=0; i<len; i++) {
chNum[s[i]]++;
}
//统计出现次数为奇数的字符
map<char, int>::iterator it;
int sum = 0;
for(it=chNum.begin(); it!=chNum.end(); it++) {
if(it->second % 2 != 0) sum++;
}
//超过一个奇数字符就无法构成回文串
if(sum > 1) {
cout << "Impossible" << endl;
return 0;
}
//统计最少交换次数
int ans = 0;
int res = len;
for(int i=0; i<(len+1)/2; i++) {
int j;
for(j=res-1; j>i; j--) {
if(s[i] == s[j]) {
while(j < res-1) {
swap(s[j], s[j+1]);
j++;
ans++;
}
res--;
break;
}
}
if(i == j) ans += ((len-1)/2 - i);
}
cout << ans << endl;
return 0;
}
#include<iostream>
#include<algorithm>
using namespace std;
int num[30010];
int main()
{
int w,n,ans=0;
cin>>w>>n;
for(int i=1;i<=n;i++)
cin>>num[i];
sort(num+1,num+n+1);
int i=1,j=n;
//要有等于,,i=j的时候,就是只剩一个,归到else里ans++
while (i<=j)
{
//最大的和最小的一组
if(num[j]+num[i]<=w)
{
ans++;
j--;
i++;
}
//大的各成一组
else
{
ans++;
j--;
}
}
cout<<ans;
return 0;
}
#include <cstdio>
#include <algorithm>
#define MAXN 105
using namespace std;
struct oil {
double d, p;
}a[MAXN];
bool cmp(oil x, oil y) {
return x.d <= y.d;
}
double D1, C, D2, P;//分别表示总距离D1,容量C,每升油行驶距离D2,出发点价格P
double dis, loc, ca, cost, reach, mn;
//分别表示加满油能跑的距离dis,当前位置loc,油箱中油量ca,花费的钱cost, reach表示加满油能到的位置
// 把P表示成当前油价,每次更新即可
int i = 1, t, n;
bool flag;
int main() {
scanf("%lf%lf%lf%lf%d", &D1, &C, &D2, &P, &n);
dis = C * D2;
for(i = 1; i <= n; i++)
scanf("%lf%lf", &a[i].d, &a[i].p);
a[0].d = 0;
for(i = 1; i <= n; i++)
if(a[i].d - a[i-1].d > dis) {
printf("No Solution\n");
return 0;
}
sort(a, a+n+1, cmp);
i = 0;
while(loc < D1) {
flag = 0;
reach = loc + dis; //表示当前能到达的最远距离
for(int j = i+1; j <= n && a[j].d <= reach; j++) { //找出比当前加油站油价更便宜的下一个加油站
if(a[j].p < P) {
flag = 1;
t = j;
break;
}
}
if(!flag) {//如果在能到达的范围没有找到 , 那么寻在当前地方加满油,直接开到下一个加油站再次反复寻找
if(reach >= D1) { //如果当前最便宜的状态下加满油能够到达终点
if((D1-loc) / D2 > ca) //如果当前油箱的油不够 ,加到刚好到终点退出
cost += ((D1-loc) / D2 - ca) * P;
break;
}
t = i + 1; //开到下一个加油站
cost += (C-ca) * P; //将油加满
ca = C - (a[t].d - loc) / D2; //减去到达下一个点耗费的油
loc = a[t].d; //更新
P = a[t].p;
i = t;
}else { //去到比当前便宜的下一个站 flag == 1
if((a[t].d - loc) / D2 > ca) { //如果油不够则加到刚好到达下一个为止
cost += ((a[t].d - loc) / D2 - ca) * P;
ca = 0;
}else //如果油够则直接减去损耗的油
ca -= (a[t].d - loc) / D2;
loc = a[t].d; //更新
P = a[t].p;
i = t;
}
}
printf("%.2lf\n", cost);
return 0;
}
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
struct jimu
{
int own,need,lack;//拥有积木数、需要积木数、缺少积木数
};
bool cmp(jimu a, jimu b)//按缺少积木从多到少排序
{
return a.lack < b.lack;
}
int main()
{
int m, n,sum=0,flag=0;
cin >> m;
for (int i = 0; i < m; i++)
{
flag = 0; sum = 0;
cin >> n;
vector<jimu>arr(n);
for (int i = 0; i < n; i++)
{
cin >> arr[i].own >> arr[i].need;
arr[i].lack = arr[i].need - arr[i].own;
}
sort(arr.begin(), arr.end(), cmp);//排序
for (int i = 0; i < n; i++)
{
if (arr[i].lack <= 0)//当前小朋友开始就有足够的积木
sum += arr[i].own;
else
{
if (sum >= arr[i].lack)
sum += arr[i].own;
else//不能完成
{
flag = 1;
break;
}
}
}
if (flag == 1)
cout << "NO" << endl;
else
cout << "YES" << endl;
}
return 0;
}
#include<iostream>
#include<algorithm>
using namespace std;
int a[13]={0},cnt=0,n,x,y;
int check(int i)
{
int j,k;
for (j=1;j<i;j++)
{
if (a[i]==a[j]||abs(a[i]-a[j])==i-j)
return 0;
}
if ((i==x-1&&a[i]==y-1) || (i==x-1&&a[i]==y) || (i==x-1&&a[i]==y+1)
|| (i==x&&a[i]==y-1) || (i==x&&a[i]==y) || (i==x&&a[i]==y+1)
|| (i==x+1&&a[i]==y-1) || (i==x+1&&a[i]==y) || (i==x+1&&a[i]==y+1)) //不能在王的9个位置
return 0;
return 1;
}
void dfs(int s)
{
int i;
if (s>n)//找到1种解
{
cnt++;
return ;
}
for (i=1;i<=n;i++)
{
if (s==x&&i==y)
continue;
a[s]=i;
if (check(s))//判断是否可以摆放皇后
dfs(s+1);//下一行
}
}
int main()
{
cin>>n>>x>>y;
dfs(1); //国王的位置是从1开始的
cout<<cnt<<endl;
return 0;
}
#include<iostream>
using namespace std;
int Recursion(int n)
{
if (n == 1)return 1;
if (n == 2)return 2;
if (n > 2)
return Recursion(n - 1) + Recursion(n - 2);
}
int main()
{
int n;
cin >> n;
cout << Recursion(n) << endl;
return 0;
}
#include<iostream>
using namespace std;
int n;
string s;
void f(int L,int R){
if(R>L){
f(L,(L+R)/2);
f((L+R)/2 +1,R);
}
int B=1,I=1,F;
for(int i=L;i<=R;i++){
if(s[i] == '0'){
I = 0;
}else if(s[i] == '1'){
B = 0;
}
}
if(B){
cout<<'B';
}else if(I){
cout<<'I';
}else{
cout<<'F';
}
}
int main(){
cin>>n>>s;
int len = s.length() -1;
f(0,len);
return 0;
}
#include <cmath>
#include <cstring>
#include <iostream>
using namespace std;
int n, length = 0, vis[1000] = {0};
string str[1000];
//返回a,b之中可以首尾相接的长度(长度越短,相接后的字符串越长)
//此处有两个特判
//一种是没有重合长度,要返回0
//另一种是两个字符串中长度最小的长度为1,会直接返回0
inline int check(string a, string b){
int p = min(a.length(), b.length());
for (int i = 1; a.length() == 1 ? i <= p : i < p; i++){
bool flag = true;
for (int j = 0; j < i; j++)
if (a[a.length() - i + j] != b[j]){
flag = false;
break;
}
if (flag == true) return i;
}
return 0;
}
//用dfs从1到n判断这些字符串能不能接上去
//(只要看两个字符串有没有重叠部分就可以了)
void dfs(string s, int length_now){
length = max(length, length_now);// 算出所有接龙情况中的最长长度
for (int i = 1; i <= n; i++){
if (vis[i] > 1) continue;
else{
int add = check(s, str[i]);
if (add != 0){
vis[i]++;
//接龙长度 = 龙的长度 + 现在接上的长度 - 重合的长度
dfs(str[i], length_now + str[i].length() - add);
vis[i]--;//恢复现场
}
}
}
}
int main()
{
cin >> n;
for (int i = 1; i <= n; i++) cin >> str[i];
cin >> str[n + 1];//“龙头”
dfs(str[n + 1], 1);
cout << length << endl;
return 0;
}
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 10+5;
int nexts[N][N], t[N];
int n, k, cnt = 0;
int main(int argc, char** argv) {
cin>> n>> k;
for(int i = 0; i < n; i++){
t[i] = i;
for(int j = 0; j < n; j++)
cin>> nexts[i][j];
}
do{
bool ok = true;
for(int i = 1; i < n; i++){
if(nexts[t[i-1]][t[i]] == 0){
ok = false;
break;
}
}
if(ok) cnt++;
if(cnt == k) break;
}while(next_permutation(t, t+n));
for(int i = 0; i < n; i++)
cout<< t[i]<< " ";
return 0;
}
#include <stdio.h>
int N, a[22], T, num=0, b[22];
void print(int y)
{
int i;
for(i=y; i>=0; i--){
printf("%d ", b[i]);
}
printf("\n");
}
void f(int x, int y,int sum)
{
if(x < 0)
{
return;
}
f(x-1, y, sum);
b[y] = a[x], sum += a[x];
if(sum == T)
{
num ++;
print(y);
}
f(x-1, y+1, sum);
}
int main()
{
int i;
scanf("%d", &N);
for(i=0; i<N; i++)
scanf("%d", &a[i]);
scanf("%d", &T);
f(N-1, 0, 0);
printf("%d", num);
return 0;
}
//bfs
思考我们的递归终止条件什么,显然不是a,b,c出界,
而是这个状态被遍历过,那么必然也从这个状态转移过
,所以在此便可终止递归,在遍历到每一个状态的时候,
标记为true,,千万不要回溯。 因为如果回溯了,那么
在最后统计答案的时候会所有状态都没有被访问过,
那么如果我们在结束递归的同时输出答案会使得答案重复
,而且无法保证c值从小到大
然后输出答案是外层循环枚举c, 内层枚举b,才能从小到大输出哦
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 21;
int A, B, C;
bool st[N][N][N];//标记每个状态是否出现
struct Node
{
int a, b, c;
}q[N * N * N];
int hh, tt;
void insert(int a, int b, int c)
{
if (!st[a][b][c])
{
q[ ++ tt] = {a, b, c};//这个状态已经出现了
st[a][b][c] = true;
}
}
void bfs()
{
q[0] = {0, 0, C};//初始状态
st[0][0][C] = true;
while (hh <= tt)//队列不空
{
auto t = q[hh ++ ];
int a = t.a, b = t.b, c = t.c;
insert(a - min(a, B - b), min(a + b, B), c);//第一个倒入第二个
insert(a - min(a, C - c), b, min(a + c, C));//第一个倒入第三个
insert(min(a + b, A), b - min(A - a, b), c);//第二个倒入第一个
insert(a, b - min(C - c, b), min(c + b, C));//第二个倒入第三个
insert(min(a + c, A), b, c - min(c, A - a));//第三个倒入第一个
insert(a, min(b + c, B), c - min(c, B - b));//第三个倒入第二个
}
}
int main()
{
cin >> A >> B >> C;
bfs();
for (int c = 0; c <= C; c ++ )
for (int b = 0; b <= B; b ++ )
if (st[0][b][c])
{
cout << c << ' ';
break;
}
return 0;
}
//DFS
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;
const int N = 21;
int A, B, C;
bool vis[N][N][N];
void dfs(int a, int b, int c) {
if (vis[a][b][c]) return;
vis[a][b][c] = true;
dfs(a - min(a, B - b), min(a + b, B), c);
dfs(a- min(a, C - c), b, min(a + c, C));
dfs(min(a + b, A), b - min(b, A - a), c);
dfs(a, b - min(b, C- c), min(c + b, C));
dfs(min(a + c, A), b, c - min(c, A - a));
dfs(a, min(b + c, B), c - min(c, B - b));
}
int main(void) {
scanf("%d%d%d", &A, &B, &C);
dfs(0, 0, C);
for (int c = 0; c <= C; c ++ )
for (int b = 0; b <= B; b ++ )
if(vis[0][b][c]) {
cout << c << ' ';
break;
}
return 0;
}
#include <cstdio>
#include <map>
#include <queue>
#include <vector>
using namespace std;
char goal[10];
int termination;
struct node
{
int step,num;
vector<char> answer;
node(int n,int s,vector<char> a)
{
num=n;
step=s;
answer=a;
}
};
void swap(char str[],int flag,bool operate)
{
if(flag==0)
{
char temp[8];
for(int i=0;i<8;++i)
{
temp[i]=str[7-i];
}
for(int i=0;i<8;i++)
{
str[i]=temp[i];
}
}
if(flag==1)
{
if(operate==true)
{
char temp=str[3];
str[3]=str[2];
str[2]=str[1];
str[1]=str[0];
str[0]=temp;
temp=str[4];
str[4]=str[5];
str[5]=str[6];
str[6]=str[7];
str[7]=temp;
}
else
{
char temp=str[0];
str[0]=str[1];
str[1]=str[2];
str[2]=str[3];
str[3]=temp;
temp=str[7];
str[7]=str[6];
str[6]=str[5];
str[5]=str[4];
str[4]=temp;
}
}
if(flag==2)
{
if(operate==true)
{
char temp=str[1];
str[1]=str[6];
str[6]=str[5];
str[5]=str[2];
str[2]=temp;
}
else
{
char temp=str[1];
str[1]=str[2];
str[2]=str[5];
str[5]=str[6];
str[6]=temp;
}
}
}
queue<node> p;
map<int,bool> mp;
int combine(int num)
{
char temp[10];
int temp1;
vector<char> answer;
node s(num,0,answer);
p.push(s);
mp[num]=true;
while(!p.empty())
{
s=p.front();
p.pop();
sprintf(temp,"%d",s.num);
if(s.num==termination)
{
printf("%d\n",s.step);
for(int i=0;i<s.step;++i)
{
if(i%60==0&&i!=0)
{
printf("%c\n",s.answer[i]);
}
else
{
printf("%c",s.answer[i]);
}
}
return 0;
}
for(int i=0;i<3;i++)
{
swap(temp,i,true);
sscanf(temp,"%d",&temp1);
if(mp.count(temp1)==0)
{
node r(temp1,s.step+1,s.answer);
r.answer.push_back(i+'A');
p.push(r);
mp[temp1]=true;
}
swap(temp,i,false);
}
}
}
int main()
{
int n;
while(~scanf("%d",&n))
{
termination=n;
for(int i=0;i<7;i++)
{
scanf("%d",&n);
termination=termination*10+n;
}
combine(12345678);
}
return 0;
}
#include<iostream>
#include<cstdio>
using namespace std;
int main()
{
int arr[10][10]=
{
0,4,3,3,4,3,2,3,1,2, //分别是 0-9所对应的0-9变换所要的次数;
4,0,5,3,2,5,6,1,5,4,
3,5,0,2,5,4,3,4,2,3,
3,3,2,0,3,2,3,2,2,1,
4,2,5,3,0,3,4,3,3,2,
3,5,4,2,3,0,1,4,2,1,
2,6,3,3,4,1,0,5,1,2,
3,1,4,2,3,4,5,0,4,3,
1,5,2,2,3,2,1,4,0,1,
2,4,3,1,2,1,2,3,1,0
};
int x;
int sum=0;
string str1,str2;
cin>>x>>str1>>str2;
for(int i=0;i<x;++i)
{
sum+=arr[str1[i]-'0'][str2[i]-'0'];
// printf("$$%d\n",sum);
}
cout<<sum;
return 0;
}
#include<iostream>
#include<queue>
using namespace std;
#define M 500
#define N 500
//上下左右UDLR,按字典序排是DLRU,即下左右上,所以d数组调整了一下
const int d[][2] =
{
1,0,
0,-1,
0,1,
-1,0,
};
string h="DLRU";
bool maze[M][N];//位置点的状态,0表示通道,1表示墙
bool visited[M][N];//标志着该点是否被访问到了
int m,n;//迷宫的实际行数和列数
struct Point //结构体,表示位置点
{
int x,y;//位置点的横纵坐标
char c;//从上一步是如何来到这一步的。 DLRU。
};
Point pre[M][N];//记录了到达本点前一步的那个点的坐标
int step;
string s="";
void print_path(Point p)//递归打印路径
{
if(p.x==0&&p.y==0)
{
return;
}
print_path(pre[p.x][p.y]);
step++;
s+=p.c;
}
void bfs()//广度优先算法bfs
{
queue<Point> Q;//定义队列Q
Point p={0,0,0};
visited[0][0]=true;//入口点被访问
Q.push(p);///入口点入队
while(!Q.empty())//当队列不为空时
{
Point head=Q.front();//读队首元素
Q.pop();//队首元素出队
int x = head.x;
int y = head.y;
if(x==m-1 && y==n-1) //到达终点
{
print_path(head);//打印
return;//到达终点,停止bfs()
}
for(int i=0; i<4; i++)
{
int r = x + d[i][0];
int c = y + d[i][1];
if(r>=0 && r<m && c>=0 && c<n && visited[r][c]==false && maze[r][c]==0)
{
visited[r][c] = true; //标记为已访问
pre[r][c] = head; //记录前一步
Point p={r,c,h[i]};
Q.push(p);//入队
}
}
}
}
int main()
{
cin>>m>>n;
for(int i=0;i<m;i++)
{
for(int j=0;j<n;j++)
{
char c;
cin>>c;
maze[i][j]=c-'0';
}
}
bfs();
cout<<step<<endl;
cout<<s<<endl;
return 0;
}
const int dirs[4][2] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
int rows, columns;
int longestIncreasingPath(int** matrix, int matrixSize, int* matrixColSize) {
if (matrixSize == 0 || matrixColSize[0] == 0) {
return 0;
}
rows = matrixSize;
columns = matrixColSize[0];
int** memo = (int**)malloc(sizeof(int*) * rows);
for (int i = 0; i < rows; i++) {
memo[i] = (int*)malloc(sizeof(int) * columns);
memset(memo[i], 0, sizeof(int) * columns);
}
int ans = 0;
for (int i = 0; i < rows; ++i) {
for (int j = 0; j < columns; ++j) {
ans = fmax(ans, dfs(matrix, i, j, memo));
}
}
free(memo);
return ans;
}
int dfs(int** matrix, int row, int column, int** memo) {
if (memo[row][column] != 0) {
return memo[row][column];
}
++memo[row][column];
for (int i = 0; i < 4; ++i) {
int newRow = row + dirs[i][0], newColumn = column + dirs[i][1];
if (newRow >= 0 && newRow < rows && newColumn >= 0 && newColumn < columns && matrix[newRow][newColumn] > matrix[row][column]) {
memo[row][column] = fmax(memo[row][column], dfs(matrix, newRow, newColumn, memo) + 1);
}
}
return memo[row][column];
}
作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/longest-increasing-path-in-a-matrix/solution/ju-zhen-zhong-de-zui-chang-di-zeng-lu-jing-by-le-2/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
class Solution {
// 上下左右的方向
int[][] dirs = new int[][]{{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
public int longestIncreasingPath(int[][] matrix) {
// 把符合题目要求的点连起来就是有一张有向无环图
// 所以我们可以使用多源BFS拓扑排序寻找最短路径的思想在这里寻找最长路径
int m = matrix.length;
int n = matrix[0].length;
// 记录每个节点的出度
int[][] outDegree = new int[m][n];
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
for (int[] dir : dirs) {
int nextI = i + dir[0];
int nextJ = j + dir[1];
// 只要旁边节点的值比它大,它的出度就加1
if (nextI >= 0 && nextJ >= 0 && nextI < m && nextJ < n && matrix[nextI][nextJ] > matrix[i][j]) {
outDegree[i][j]++;
}
}
}
}
// 多源BFS(可以跟上面的循环合在一起)
// 为了更清晰,这里单独写这个循环
Queue<int[]> queue = new LinkedList<>();
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (outDegree[i][j] == 0) {
queue.offer(new int[] {i, j});
}
}
}
int ans = 0;
while (!queue.isEmpty()) {
ans++;
// 一次遍历一批,每遍历一批,相当于最长路径又加了一
int size = queue.size();
for (int c = 0; c < size; c++) {
int[] pos = queue.poll();
int i = pos[0];
int j = pos[1];
for (int[] dir : dirs) {
int preI = i + dir[0];
int preJ = j + dir[1];
if (preI >= 0 && preI < m && preJ >= 0 && preJ < n && matrix[preI][preJ] < matrix[i][j]) {
// 指向当前元素的节点的出度减1,减到0了入队
if (--outDegree[preI][preJ] == 0) {
queue.offer(new int[] {preI, preJ});
}
}
}
}
}
return ans;
}
}
作者:tong-zhu
链接:https://leetcode-cn.com/problems/longest-increasing-path-in-a-matrix/solution/tong-ge-lai-shua-ti-la-yi-ti-si-jie-bfs-agawl/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
#include <bits/stdc++.h>
using namespace std;
const int maxx = 10010;
struct node{
int s; //start,区间的左端点
int e; //end,区间的右端点
} p[maxx]; //区间数组
bool cmp(node n1, node n2) {
if (n1.e != n2.e) {
return n1.e < n2.e;
}
return n1.s > n2.s;
}
int a[maxx]; //存储点
int main() {
int n, m;
cin >> n >> m;
for (int i = 0; i < n; i++) { //n个点
cin >> a[i];
}
for (int i = 0; i < m; i++) { //m个区间
cin >> p[i].s >> p[i].e;
}
sort(p, p+m, cmp);
int k, i, j, st = 0;
for (k = 0; k < n; k++) { //表示点的个数-1,因为是从0开始的
int _max = -1;
for (i = 0; i <= n; i++) { //遍历所有点
for (j = st; j < m; j++) {
if (p[j].s > a[i] || p[j].e < a[i]) {
break;
}
}
if (j > _max) { //看这个点最多可以满足多少个区间。
_max = j;
}
}
st = _max; //下次开始的时间就在上一次点的地方开始,寻找满足的点
if (st == m) { //所有的线段满足了,就直接退出。
break;
}
}
if (k == n) {
cout << -1 << endl;
} else {
cout << k+1 << endl;
}
return 0;
}
#include<iostream>
using namespace std;
int n,m;
bool a[40];
int dfs(int len){
if(len==n)return 1;
if(a[len]==true||len>n)return 0;
return dfs(len+1)+dfs(len+2);
}
int main(){
int tmp;
cin>>n>>m;
for(int i=1;i<=m;i++){
cin>>tmp;
a[tmp]=true;
}
cout<<dfs(1)<<endl;
return 0;
}
#include<iostream>
#include<cstring>
using namespace std;
int f[41],a[41];
int n,m;
int main()
{
cin>>n>>m;
memset(f,-1,sizeof(f));
f[0]=1;
f[1]=1;
for(int i=0;i<m;i++){
int tmp;
cin>>tmp;
f[tmp-1]=0;
}
for(int i=2;i<n;i++){
if(f[i]!=0)f[i]=f[i-1]+f[i-2];
}
cout<<f[n-1];
return 0;
}
#include<iostream>
#include<algorithm>
#include<cstdio>
using namespace std;
typedef long long ll;
const int N = 50;
int n, m, ans = -1e9;
int a[N];
bool st[N];
void dfs(int idx, int now, int sum)
{
if(now == m)
{
ans = max(ans, sum);
return;
}
if(idx > n) return; //n为种树位置
if(idx==n) //第n号要单独判断
{
if(now==m-1 && !st[1] && !st[n-1])
{
sum += a[n];
ans = max(ans, sum);
}
return;
}
st[idx] = true;
dfs(idx + 2, now + 1, sum + a[idx]); //选idx号,那么下一个只能从idx+2号开始选
st[idx] = false; //恢复现场
dfs(idx + 1, now, sum); //不选idx号,那么下一个可以从idx+1号开始选
}
int main()
{
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; ++i)
scanf("%d", &a[i]);
if(n < m * 2)
{
puts("Error!");
return 0;
}
dfs(1, 0, 0);
printf("%d\n", ans);
return 0;
}
用天平称重就是三种情况:
1.不用这个砝码
2.物左码右
3.将砝码放在物品那个盘
然后用一个数组s存放前i个砝码的重量和,注意有可能还是会超时,如果超时可以试试将砝码重量排好序再计算s数组。
判断是否能够称出的条件的顺序要注意。
#include <bits/stdc++.h>
using namespace std;
int w[25];
int remain[25]= {0};
int ok;
int n;
void DFS(int t,int f)
{
if(t==0)
{
ok=1;
return ;
}
if(abs(t)>remain[f])
return ;
for(; f<n; f++)
{
DFS(t-w[f],f+1);
DFS(t+w[f],f+1);
}
}
int main()
{
int m;
cin>>n>>m;
for(int i=0; i<n; i++)
cin>>w[i];
sort(w,w+n);
for(int i=n-1; i>=0; i--)
remain[i]=w[i]+remain[i+1];
while(m--)
{
ok=0;
int thing;
cin>>thing;
DFS(thing,0);
if(ok)
cout<<"YES"<<endl;
else
cout<<"NO"<<endl;
}
return 0;
}
#include<iostream>
#include<cstring>
using namespace std;
int n,m;
int vis[20];
int a[20];
int t;
int ans = -0x3f3f3f3f;
void dfs(int cnt,int sum)
{
if(cnt == m)
{
ans = max(ans,sum);
return ;
}
for(int i = 1;i <= n;i++)
{
if(!vis[i])
{
vis[i] = 1;
dfs(cnt+1,sum*a[i]);
vis[i] = 0;
}
}
}
int main(void)
{
cin>>t;
while(t--)
{
ans = -0x3f3f3f3f;
memset(vis,0,sizeof vis);
cin>>n>>m;
for(int i = 1;i <= n;i++)
{
cin>>a[i];
}
dfs(0,1);
cout<<ans<<endl;
}
return 0;
}
#include <iostream>
#include <cstring>
using namespace std;
const int N = 1010;
char g[N][N];
bool st[N][N];
int n;
int total, brink;
const int dx[] = {-1,0,1,0}, dy[] = {0,1,0,-1};
void dfs(int x,int y) {
st[x][y] = true;
total ++;
for(int i = 0;i < 4;i ++)
if(g[x + dx[i]][y + dy[i]] == '.') {
brink ++;
break;
}
for(int i = 0;i < 4;i ++) {
int tx = x + dx[i], ty = y + dy[i];
if(tx < 0 || tx >= n || ty < 0 || ty >= n) continue;
if(g[tx][ty] == '#' && !st[tx][ty]) {
dfs(tx,ty);
}
}
}
int main()
{
cin >> n;
for(int i = 0;i < n;i ++) cin >> g[i];
int cnt = 0;
for(int i = 0;i < n;i ++)
for(int j = 0;j < n;j ++)
if(g[i][j] == '#' && !st[i][j])
{
total = brink = 0;
dfs(i,j);
if(total == brink) cnt ++;
}
cout << cnt << endl;
return 0;
}
#include<bits/stdc++.h>
using namespace std;
int n;
int stick[66];
int sum=0;
int visited[66];//标记是否枚举
/*
target代表要求的长度
now代表现在所拼好的长度
count代表需要拼好的个数
x代表该次枚举的木棍编号
*/
bool dfs(int x,int target,int now,int count)//x当前枚举的最小长度--now现在已经拼完的长度--sum现在拼完的根数
{
if(count==sum/target) //当拼好的木棍数==需要拼好的木棍数时 ,返回true
return true;
if(now==target)//当当前拼好的木棍长度达到所需木棍长度时,如果此时之后的小木棍可以拼出要求的木棍长度,返回true
{
if(dfs(1,target,0,count+1)) //dfs深搜 下一个元素
return 1;
}
for(int i=x;i<=n;i++)//枚举x之后的小木棍
{
if(!visited[i]&&now+stick[i]<=target)//下标为I的元素没有被访问过,并且现在已经拼接完的长度小于等于目标长度
{
visited[i]=1;//标记访问过
if(dfs(i+1,target,now+stick[i],count)) //进入下一次dfs(现在拼接的根数,下一个元素下标,目标长度,现在已经拼接的长度加上stick[i]木棍的长度,因为两者加载一起还没有超过target)
return true;
visited[i]=0;//回溯恢复标记值
//剪枝操作
if(stick[i]==target-now||now==0) //如果现在拼接的木棍的长度为0,或者此时截断的木棍长度==目标长度-现在拼接的木棍长度,跳出循环.可以凑出要求木棍长度时退出枚举
break;
while(stick[i]==stick[i+1]) //排除相同项的重复遍历
i++;
}
}
return 0;
}
int main(){
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>stick[i];//输入stick
sum+=stick[i];//计算木棍总和
}
sort(stick+1,stick+1+n,greater<int>());//从大到小进行排序
for(int i=stick[1];i<=sum;i++)//从断开的小木棍中的最大值开始遍历,一直到sum的长度,这是遍历所有可能的原始木棍的长度。
{
if(sum%i!=0)//如果不能整除,直接排除 剪枝操作,最后组装的木棍个数,肯定是总长度sum与木棍原始长度整除得到
continue;//直接跳过这个长度的枚举
if(dfs(1,i,0,0))//深搜递归,下标从1开始,因为输入的时候就是从下标1开始存储木棍的长度的。
{
cout<<i;//i is answer。 because we want a number which is smaller
break;//跳出
}
}
return 0;
}
#include<iostream>
using namespace std;
const int MAX=15;
const int INF=0x3f3f3f3f;
int n,m;
int size,sum,now,ans=INF;
int map[MAX][MAX];
int vis[MAX][MAX];
int go[][2]={{1,0},{0,1},{-1,0},{0,-1}};
void dfs(int x,int y)
{
vis[x][y]=1;
now+=map[x][y];
size++;
if(size>=ans) return;//剪枝:当某种取法的格子数量已经大于前面某次的数量就不必再继续搜索
if(now+now==sum){
ans=size;
return;
}
for(int i=0;i<4;i++)//往四个方向走以寻求可以剪的地方
{
int new_x=x+go[i][0],new_y=y+go[i][1];
if(vis[new_x][new_y]==0 && new_x>=1 && new_x<=n
&& new_y>=1 && new_y<=m)
{
dfs(new_x,new_y);
vis[new_x][new_y]=0; //回溯的时候需要将已访问过的点还原为未访问
size--; //同时将用于标记格子数的变量减1
now-=map[new_x][new_y]; //以及把用于记录当前访问格子总和的变量还原
}
}
}
int main()
{
cin>>m>>n;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++){
cin>>map[i][j];
sum+=map[i][j];
}
dfs(1,1);
if(ans==INF) cout<<0<<endl;
else cout<<ans<<endl;
return 0;
}
#include<iostream>
#include<vector>
using namespace std;
const int MAX=105;
bool map[MAX][MAX]; //map[x][y]表示x和y认识
int n,m;
int ans=MAX; //最开始必须给ans赋值一个最大值(为最多的人数即可)
vector<int> classroom[MAX]; //二维向量classroom[i]=x表示
void dfs(int order,int roomNum) //order表示某个学生的序号,roomNum表示当前教室的数量
{
if(roomNum>=ans) return; //当现在安排的教室数量已经大于了最小的教室数量的话放弃搜索并回退
if(order>n){ //安排的学生数量已经大于所有的学生,就表示已经安排完了所有的学生
ans=roomNum;
return;
}
for(int i=1;classroom[i].size();i++) //遍历所有教室
{
int j,len=classroom[i].size();
for(j=0;j<len;j++) //检测当前教室是否存在一个人与将要被安排的学生认识
if(map[order][classroom[i][j]]) break;
if(j==len) //说明当前教室中没有人与当前order的学生认识
{
classroom[i].push_back(order); //在当前教室插入此学生
dfs(order+1,roomNum); //继续安排下一个
classroom[i].pop_back(); //回退时需要把这个学生从当前教室清除掉
}
}
classroom[roomNum+1].push_back(order); //开一间新教室给当前学生
dfs(order+1,roomNum+1); //继续安排下一个
classroom[roomNum+1].pop_back(); //回退后需要把这个学生从当前教室清除掉
}
int main()
{
int x,y;
cin>>n>>m;
for(int i=0;i<m;i++)
{
cin>>x>>y;
map[x][y]=map[y][x]=1;
}
dfs(1,0);
cout<<ans<<endl;
return 0;
}
#include <iostream>
using namespace std;
const int N = 20;
const char X[3] = {' ', '+', '-'}; // ascii 码 ' ' < '+' < '-'
int n;
char ans[N];
void print(){
for(int i=1; i<n; i++) //循环前n-1个
{
cout << i << ans[i]; //输出数字加符号
}
cout << n << endl; //输出最后一个数字
}
//计算表达式的值。
int check(){ //重点,如何计算值为0,尤其是空格的情况
int sum = 0, num = 1; //可以理解预设首个运算符必然是 0+1
char lastop = '+'; //1前面的可以认为是'+'
for(int i=1; i<n; i++) {
if(ans[i] == ' ') //如果该符号是空格的话
num = num * 10 + (i + 1); //举个例子2 3应该是2*10+3=23
else {
if(lastop == '+') sum += num; //如果不是空格直接加减
else sum -= num;
num = i+1; lastop = ans[i]; //这里num和lastop的值需要更新,很重要
}
}
if(lastop == '+') sum += num; //对最后一个数进行判断
else sum -= num;
return sum;
}
//搜索 n-1 个位置,每个位置可选'+' ,'-' 或' '
//cur 表示当前所搜索的位置编号[1, n-1]。
void dfs(int cur){ //全排列问题,输入当前位置
if(cur > n-1 ) { //超过n-1结束
if(check() == 0) print(); //检查算式的值为0则输出
return;
}
for(int i=0; i<=2; i++) { //遍历三种符号
ans[cur] = X[i]; //ans数组存储符号
dfs(cur + 1); //搜索下一个
}
}
int main() {
cin >> n; //假如n=7则有n-1=6个空隙
//0 + 1
dfs(1); //从 1 和 2 之间的间隔开始搜索。
return 0;
}
#include<cstdio>
#include<iostream>
using namespace std;
int main()
{
int n;
while(cin>>n)
{
long long maxsum =-1, maxhere = -1;
long long x ;
for(int i = 0;i<n;i++)
{
cin>>x;
if(maxhere<=0){
maxhere = x;
}
else{
maxhere += x;
}
if(maxhere>maxsum)
maxsum = maxhere;
}
cout<<maxsum<<"\n";
}
}
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxx=1e5+100;
struct node{
string s;
int num;
node(string tt,int a)
{
s=tt,num=a;
}
};
string s;
int n;
inline int bfs()
{
map<string,bool> mp;
queue<node> q;
mp[s]=1;
q.push(node(s,0));
string tt;
while(q.size())
{
node u=q.front();
q.pop();
if(u.s.find("2012")!=-1) return u.num;
tt=u.s;
for(int i=0;i<tt.length()-1;i++)
{
swap(tt[i],tt[i+1]);
if(mp[tt]==0)
{
mp[tt]=1;
q.push(node(tt,u.num+1));
}
swap(tt[i],tt[i+1]);
}
}
return -1;
}
int main()
{
cin>>n>>s;
cout<<bfs()<<endl;
return 0;
}
// Chapter14_5.cpp : Defines the entry point for the application.
// 数的划分
// 将整数n分成k份,且每份不能为空,任意两种划分方案不能相同(不考虑顺序)。
// 求整数n分为k份,共有多少种不同的分法。
// 输入两个整数n,k(6<n<=200,2<=k<=6)。
// 输出一个整数,即有几种不同的分法。
#include "stdafx.h"
#include<iostream>
using namespace std;
int main()
{
int n,k;
cout << "输入整数n和划分的份数k:";
cin >> n >> k;
int dp[201][7];
//全部初始化为0
memset(dp,0,sizeof(dp));
//对于dp[0][0]作特殊处理(为了后面的动态转移方程能够起作用)
dp[0][0] = 1;
int i,j;
//i的取值范围是1~n(不能超过给定的整数)
for(i=1;i<=n;i++)
//j的范围是1~k(不能超过需要划分的份数)
for(j=1;j<=k;j++)
{
//划分的分数要小于等于该数本身
if(i>=j)
//动态转移方程
dp[i][j] = dp[i-j][j] + dp[i-1][j-1];
}
cout << "共有" << dp[n][k] << "种分法" << endl;
system("pause");
return 0;
}
#include<iostream>
using namespace std;
int main()
{
int dp[40][40]={0};
int n,m;
int i,j,a,b;
cin>>n>>m;
dp[0][1]=1;//设小蛮位置为1,则初值为1
for(i=1;i<=m;i++)//从1次到m次
{
for(j=1;j<=n;j++)//从位置1到位置n
{
a=j-1;//左位为当前位置-1
if(a==0) a=n;//若左位超出范围,令其为n
b=j+1;//右位为当前位置+1
if(b==n+1) b=1;//若右位超出范围,令其为1
dp[i][j]=dp[i-1][a]+dp[i-1][b];//第i次传球到位置j的方案数=第i-1次j位的左位方案数+第i-1次j为右位方案数
}
}
cout<<dp[m][1]<<endl;
return 0;
}
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n;
cin>>n;
int solve[n+1][n+1];
for(int j=0;j<=n;j++)
solve[1][j]=1;
for(int i=2;i<=n;i++)
for(int j=0;j<=n;j++)
{
solve[i][j]=solve[i-1][j];
if(j>=i)
solve[i][j]+=solve[i][j-i];
}
cout<<solve[n][n]<<endl;
return 0;
}
#include<bits/stdc++.h>
using namespace std;
#define MAX 100000
int dp[MAX],a[105];
int gcd(int a,int b) {return b == 0 ? a : gcd(b,a % b);}
int main()
{
int n,g,num = 0;
cin >> n;
for(int i = 0;i < n;i++) cin >> a[i];
g = gcd(a[0],a[1]);
for(int i = 2;i < n;i++) g = gcd(g,a[i]);
if(g != 1) cout << "INF" << endl;
else{
dp[0] = 1;
for(int i = 0;i < n;i++)
for(int j = 0;j < MAX;j++)
if(dp[j]) dp[j + a[i]] = 1;
for(int i = 0;i < MAX;i++) if(!dp[i]) num++;
cout << num << endl;
}
return 0;
}