/*
有一堆石子,A,B两人轮流从中取出石子,每次取出的石子数目只能为1,3,7或8,最后一枚石子谁取到就是输方。
A,B两人都足够聪明,不会做出错误的判断。现给出一定数目的石子,A先取石子,计算A最终是输是赢,赢用1表示,
输用0表示.
输入描述
第一行为一个整数n(0< n <=100),表示玩n局,接下来n行每行有一个整数,表示对应的局提供的石子数(不大于
10000),
输出描述
编程输出A对应的n局是赢是输,赢输出1,输输出0.
3
1
3
10
0
0
1
*/
#include <iostream>
using namespace std;
int a[10005]={1,0,1,0,1,0,1,0,1};
int f( int n)
{
if(n<8) return a[n];
else return !(f(n-1)&&f(n-3)&&f(n-7)&&f(n-8));
}
int main()
{
int b,n;
cin>>n;
while(n--)
{
cin>>b;
cout<<f(b)<<endl;
}
return 0;
}
//最大公约数
#include <iostream>
using namespace std;
int gcd (int a,int b)
{
if(a%b==0) return b;
else {
return (a-b)>b ? gcd(a-b,b): gcd(b,a-b);
}
}
int main()
{
int a,b,t;
cin>>a>>b;
if(a<b) {t=a;a=b;b=t;};
cout<<gcd(a,b);
return 0;
}
/*
现有四个人做传球游戏,要求接球后马上传给别人。
由甲先传球,并作为第1次传球,
求经过n次传球仍回到发球人甲手中的传球方式的种数。
整数n,已知n<20
#include <iostream>
using namespace std;
int f[25],g[25];
int main()
{
int n;
cin>>n;
f[1]=0;g[1]=1;
for(int i=2;i<=n;i++)
{
f[i]=3*g[i-1];
g[i]=f[i-1]+2*g[i-1];
}
cout<<f[n];
return 0;
}
螺旋矩阵
/*
25 24 23 22 21
10 9 8 7 20
11 2 1 6 19
12 3 4 5 18
13 14 15 16 17
*/
#include<iostream>
#include<stdio.h>
using namespace std;
int main()
{
int t,n,i,j,s=1,e,a[100][100];
cin>>n;
i=j=n/2;
e=n*n+1;
for(int j=0;j<n;j++)
{
e--;
a[0][j]=e;
}
a[i][j]=1;
for(int k=1;k<n;k++)
{
for(int g=2;g>0;g--)
{
t=k;
if(k%2==0)
{
if(g==2)
while(t--)
{
j=j+1;
s++;
a[i][j]=s;
}
else if(g==1)
while(t--)
{
i=i-1;
s++;
a[i][j]=s;
}
}
else
{
if(g==2)
while(t--)
{
j=j-1;
s++;
a[i][j]=s;
}
else if(g==1)
while(t--)
{
i=i+1;
s++;
a[i][j]=s;
}
}
}
}
for(int i=0;i<n;i++)
{
for(int j=0;j<n-1;j++)
{
printf("%-5d",a[i][j]);
}
cout<<a[i][n-1]<<endl;
}
}
/*
现有四个人做传球游戏,要求接球后马上传给别人。
由甲先传球,并作为第1次传球,
求经过n次传球仍回到发球人甲手中的传球方式的种数。
整数n,已知n<20
*/
#include <iostream>
using namespace std;
int f[25],g[25];
int main()
{
int n;
cin>>n;
f[1]=0;g[1]=1;
for(int i=2;i<=n;i++)
{
f[i]=3*g[i-1];
g[i]=f[i-1]+2*g[i-1];
}
cout<<f[n];
return 0;
}
最大字段和
#include <stdio.h>
int main()
{
int i,a[100005],k,ans=0,res=0;
while(~scanf("%d",&k))
{
ans=0,res=0;
for(i=0;i<k;i++)
{
scanf("%d",&a[i]);
}
for(i=0;i<k;i++)
{
ans+=a[i];
if(ans<0) ans=0;
if(ans>=res) res=ans;
}
printf("%d",res);
}
return 0;
}
/*
326.0/1背包问题 (20分)(贪心,递归)
C时间限制:3000 毫秒 | C内存限制:3000 Kb
题目内容:
物品集合U={u1,u2…un},体积分别为s1,s2……sn,价值分别为v1,v2….vn;容量C的背包。设计算法实现放入背包的物品价值最大。
输入描述
第一行输入物品数n,第二行输入每个物品体积,第三行输入每个物品的价值,第四行输入背包的容量C
输出描述
输出最大价值数。
输入样例
3
3 4 5 //体积 u
4 5 6 //价值 v
10
输出样例
11
*/
#include <iostream>
#include<cstring>
using namespace std;
int dp[1000][1000],v[1000],u[1000];
int knapsack(int i,int j)
{
int value;
if(dp[i][j]<0)
{
if(j<u[i])
{
value=knapsack(i-1,j);
}
else
{
value=max(knapsack(i-1,j),v[i]+knapsack(i-1,j-u[i]));
}
dp[i][j]=value;
}
return dp[i][j];
}
int main()
{
int i,j,n,c;
cin>>n;
for(i=1;i<=n;i++) cin>>u[i];
for(i=1;i<=n;i++) cin>>v[i];
cin>>c;
for(i=1;i<=n;i++)
for(j=1;j<=c;j++)
dp[i][j]=-1;
cout<<knapsack(n,c);
return 0;
}
/*
1489.特大背包问题 (20分)
C时间限制:1000 毫秒 | C内存限制:10000 Kb
题目内容:
现在有一个容量为C的背包和N个重量和价值已知的物品. 现在要从这n个物品中挑选出一些物品, 使得选择的物品的总重量不超过背包的容量, 且总价值最大.
此题的数据范围:
1 <= C <= 10^8(10的8次方)
1 <= N <= 100
输入描述
有多组测试数据. 第一行一个正整数T(T<=15), 表示测试数据组数.
对于每组测试数据:
第一行两个正整数N和C, 分别表示物品的数量和背包的容量.
接下来N行, 每行两个正整数w,v ,分别表示对应物品的重量和价值(1<= w <= 10^7, 1<= v <= 100)
输出描述
输出一个正整数, 表示在所选物品不超过背包容量的情况下, 能够得到的最大价值.
输入样例
1
3 10
5 10
5 10
4 12
输出样例
22
*/
#include <iostream>
#include<cstring>
using namespace std;
long long int w[10000],v[10000],dp[10000];
int main()
{
int t;
cin>>t;
while(t--)
{
long long int i,j,n,c,V=0;
cin>>n>>c;
for(i=1;i<=n;i++)
{
cin>>w[i];
cin>>v[i];
V+=v[i];
}
memset(dp,1000000010,sizeof(dp)); ///要求最小容量,初始化为最大值;
dp[0]=0;
for(i=1;i<=n;i++)
for(int j = V ;j >= v[i];j--)
dp[j]= min( dp[j] , dp[j-v[i]] + w [i]);
for( i=V ;i>=0 ; i--)
if(dp[i]<=c)
{
cout<<i<<endl; ///此处输出i,即为满足条件的最大价值
break;
}
}
return 0;
}
/*
502.矩阵连乘最少计算量 (10分)
C时间限制:3000 毫秒 | C内存限制:3000 Kb
题目内容:
n个矩阵A1,A2,…,An, ,如果其维度分别为d0xd1, d1xd2, …dn-1xdn,则可以进行连乘运算A1A2A3…An .
连乘运算可以采取不同的顺序进行,如(A1A2)A3 和 A1(A2A3),这两种顺序的消耗乘法计算量是不同的,前者是
d0.d1.d2+d0.d2.d3,后者d0.d1.d3+d1.d2.d3.
第1步选择哪两个,第2步又选择哪两个,一直到最后算出结果需要做n-1次决定。其中有一种计算顺序使得
A1A2A3…An总的乘法计算量最小。
输入描述
第一行输入n
第二行输入维度向量d0,d1,…dn
输出描述
输出所需的最少乘法次数。
输入样例
4
2 3 2 4 3
输出样例
48
*/
#include <iostream>
#define MAX 10000
using namespace std;
int main()
{
int a[1000],b[100][100];
int i,j,k,dis,n;
cin >> n;
for(i=0;i<=n;i++)
{
cin>>a[i];
}
for(i=0;i<=n;i++) b[i][i]=0;
for(dis=1;dis<n;dis++)
for(i=1,j=1+dis;i<n;i++,j++)
{
b[i][j]=MAX;
for(k=i;k<j;k++)
{
b[i][j] = min(b[i][j],b[i][k]+b[k+1][j]+a[i-1]*a[k]*a[j]);
}
}
cout<<b[1][n]<<endl;
return 0;
}
思路: 区间dp, 设dp[i][j]表示第i个矩阵到第j个矩阵之间合并的最少相乘次数
则递归方程为: dp[i][j] = min(dp[i][j], dp[i][k] + dp[k + 1][j] + d[i-1]*d[k]*d[j]); i < k < j;
需要知道相邻矩阵的乘法规则:A1(x1, y1)* A2(x2, y2) = x1 * y1 * y2;(x表示行,y表示列)
递归做法
#include <iostream>
using namespace std;
int dp[100][100];
int a[100];
int n;
int fun(int i, int j){
if(i == j)
return dp[i][j];
if(i == j - 1)
return dp[i][j] = a[i - 1] * a[i] * a[j];
if(i < j - 1){
dp[i][j] = 10000000;
for(int k = i + 1; k < j; k++)
dp[i][j] = min(dp[i][j], fun(i, k) + fun(k + 1, j) + a[i - 1] * a[j] * a[k]);
}
return dp[i][j];
}
int main(){
cin >> n;
for(int i = 0; i <= n; i++)
cin >> a[i];
cout << fun(1, n);
return 0;
}
/*
第一行输入整数n,表示n个事情。随后输入n行,每行包括一个事情的截止日(不大于n)和处理收益。
输出描述
输出最大的总收益。
输入样例
5
2 5
2 7
2 6
2 8
3 3
输出样例
18
*/
#include <iostream>
#include <algorithm>
#include <string.h>
const int maxn=10000;
using namespace std;
struct node{
int endline;
int value;
}a[maxn];
bool cmp(node a,node b)
{
return a.value>b.value ;
}
int main()
{
int n,b[maxn+5],ans=0;
cin>>n;
for(int i=0;i<n;i++)
{
cin>>a[i].endline>>a[i].value;
}
sort(a+1,a+n+1,cmp);
memset(b,0,sizeof(b));
for(int i=1;i<=n;i++)
{
if(b[a[i].endline]==0)
{
b[a[i].endline]=a[i].value;
ans+=a[i].value;
}
else
{
int j=a[i].endline;
while(b[j]&&j>=1) j--;
if(b[j]==0&&j>=1)
{
b[j]=a[i].value;
ans+=b[j];
}
}
}
cout<<ans<<endl;
}