1005. Stone Pile
///背包思想,就是满背包思想,尽可能的装满一半或者一半多1的量! 其实数据量不大,还可以用爆搜,对于每一种物品,选择房还是不放! DFS,然后对全局变量ans取最小的结果既可以了
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <queue>
#include <stack>
#include <math.h>
using namespace std;
const int MAX = 2004000;
int dp[MAX];
int a[25];
int sum;
int main()
{
//freopen("in","r",);
int n,k;
while( ~scanf("%d",&n) )
{
sum=0;
memset(dp,0,sizeof(dp));
for(int i=0;i<n;++i)
{
scanf("%d",&a[i]);
sum+=a[i];
}
int cnt=(sum+1)/2;///这里为什么要加1呢? 因为尽可能的装满一半,或者一半多一点;
dp[0]=1;
int ans=0;
for(int i=0;i<n;++i)
{
for(int j=cnt;j>=a[i];j--)
{
if(dp[j-a[i]])
{
if(j>ans)ans=j;
dp[j]=1;
}
}
}
ans=sum-ans-ans;
ans=ans<0?-ans:ans;
printf("%d\n",ans);
}
return 0;
}
///下面这个代码是别人的DFS
#include<iostream>
#include<stdlib.h>
#define maxn 27
#define INF 20000007
using namespace std;
long n,sum,ans,w[maxn];
void dfs(long dep,long now)
{
if(dep>n)
{
if(ans>abs(now-(sum-now))) ans=abs(now-(sum-now));
return;
}
dfs(dep+1,now);
dfs(dep+1,now+w[dep]);
}
int main()
{
cin>>n;
sum=0;
for(long i=1;i<=n;i++)
{
cin>>w[i];
sum+=w[i];
}
// Input
ans=INF;
dfs(1,0);
cout<<ans<<endl;
return 0;
}
来源: <http://www.cppblog.com/rakerichard/archive/2010/09/05/125959.html>
1009. K-based Numbers
dp1009
#include<iostream>
#include<limits>
#include<cstring>
#include<cmath>
using namespace std;
long long dp[20][20];
///dp[i][0]表示某位为0的可行的组合,dp[i][1]表示某位上为1的可行的组合
/// 最开头的位不能为0,然后某一位可以为0的话要看前面的数字是否是非0的;
///如果要为1的话要看前面的数字为0和非0的个数*这一位可能的情况k-1
///本来这道题想要用容斥原理去做,先求n-1上非法的组合数,然后再*(k-1)即可,但是前面较小的
///数据都能过但是较大的数字过不了,对拍之后! 所以可能的情况是:这道题不适合用容斥原理,因为
///他本身就不符合容斥原理!
int main()
{
long long n,k;
long long ans;
while(cin>>n>>k)
{
dp[0][0]=0;
dp[0][1]=k-1;
for(int i=1;i<n;++i)
{
dp[i][0]=dp[i-1][1];
dp[i][1]=(dp[i-1][0]+dp[i-1][1])*(k-1);
}
cout<<dp[n-1][1]+dp[n-1][0]<<endl;
}
return 0;
}
1010. Discrete Function
#include<iostream>
#include<cmath>
#include<stdlib.h>
using namespace std;
long long num[100005];
int main()
{
int n;cin>>n;
int ans1=1,ans2=2;
cin>>num[1]>>num[2];
long long tmax=llabs(num[2]-num[1]);
for(int i=3;i<=n;++i)
{
cin>>num[i];
if(llabs(num[i]-num[i-1])>tmax){tmax=llabs(num[i]-num[i-1]); ans1=i-1;ans2=i;}
}
cout<<ans1<<" "<<ans2<<endl;
return 0;
}
1011. Conductors
#include <iostream>
#include <cmath>
using namespace std;
int main()
{
double p, q, i;
cin>>p>>q;
p = p * 0.01 + 1e-8; //严格按照题目要求
q = q * 0.01 - 1e-8;
for (i=1; floor(i*q) - ceil(i*p)<0; i++);
cout<<i<<endl;
}
1012. K-based Numbers. Version 2
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <queue>
#include <stack>
#include <math.h>
using namespace std;
const int MAX = 1010;
int dp[20][200][MAX];
int len[20][200];
int main()
{
int n,k;
memset(dp,0,sizeof(dp));
for(int i=2; i<=10; i++)
{
len[i][1] = len[i][2] = 1;
dp[i][1][0] = i-1;
dp[i][2][0] = (i-1)*i;
}
for(int i=2; i<=10; i++)///控制进位制
for(int k=3; k<=180; k++)///控制位数
{
int mlen = max(len[i][k-1],len[i][k-2]);///获取位数
for(int j=0; j<mlen; j++)
{
dp[i][k][j] += (i-1)*(dp[i][k-1][j] + dp[i][k-2][j]);/// i*(i-1)*其他=(i-1)*i*其他
if( dp[i][k][j] >= 10 )
{///进位
dp[i][k][j+1] += dp[i][k][j]/10;
dp[i][k][j] %= 10;
}
}
int j = mlen;
if( dp[i][k][j] )
j++;
while( dp[i][k][j] >= 10 )
{///再进位
dp[i][k][j+1] += dp[i][k][j]/10;
dp[i][k][j] %= 10;
j++;
}
len[i][k] = j;
}
while( ~scanf("%d%d",&n,&k) )
{
for(int i=len[k][n]-1; i>=0; i--)///为什么要循环输出呢?! 因为是大数嘛! 所以一个存不下啊!!
printf("%d",dp[k][n][i]);
printf("\n");
}
return 0;
}
1014. Product of Digits
给一个n,找出最小的数,使其每一位的乘积=n;(0<=n<10^9)想了预处理或者分段预处理,但都没能解决这个题,本来我是按照,先用最小的除,然后用较大的输出,把能整出的凑成一个数! 但是发现不对啊
比如16=(2222)是错误的!
后来看了别人的代码才明白,是贪心处理,否则没有更好的高效的算法…… 当初就应该想到的,仔细分析下题意,明白题目本质就好了!
让ans最小,那么除最高位之外的每一位尽可能的大,才能使的总位数最少,而且能保证位数相同的情况下最高位最小,这样才能保证整体最小(最后逆序输出)
总结一下: 要想最小,首先位数少; 在总位数相同的情况下,最高位最小!
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
int main()
{///1014
int n, i, j = 0;
cin>>n;
if (0 == n) { cout<<10<<endl;return 0 ;}
else if (1 == n){ cout<<1<<endl; return 0;}///!!!这里的答案很无语啊
int a[100];
for (i = 9; i > 1; i--)
while (n % i == 0)
{///循环多次/i,直到不能整除
a[j] = i; //cout<<i<<" ==== "<<a[j]<<endl;
j++;
n /= i;
}
if (a[0] == 0 || n != 1)
cout<<-1<<endl;
else for (j--; j >= 0; j--) cout<<a[j];///逆序输出
return 0;
}
给一棵苹果二叉树,每个节点随机编号,分别是1--n,不重复,然后保留其中的q个枝条,每个纸条上都有一定数量的苹果,那么求剩下的苹果的数量最多是多少!
就好比图,边的权值就是苹果的数目!
此题用的是动态规划,将边上的权值下放到节点上,然后又知道此题1节点必须是根节点(而且跟节点不能去掉),那么好了; 此题就是最后dp[1][q]; 保留根节点1还有q个枝条能剩下多少苹果! 那么这q个枝条到底是从左子树上来的还是从右子树上来的?! 那怎么办呢?! 枚举对于一个节点pot,枚举i ,TreeDP(tree[pot].lc,i)+TreeDP(tree[pot].rc,q-i) 然后从中选一个最小的!
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
#define MAX 110
typedef struct
{
int val;
int lc,rc;///左右孩子
}Node;
Node tree[MAX];
int vis[MAX];
int n,q;
int map[MAX][MAX];
int dp[MAX][MAX];
void CreateTree(int pot)
{
vis[pot]=1;
int li=0,ri=0;
for(int i=1;i<=n;++i)
{
if(!vis[i]&&map[pot][i])
{
if(!tree[pot].lc){li=i;tree[pot].lc=i; tree[i].val=map[pot][i];}///这里不光指示边的权值下方,还指明了左右儿子的编号
else{ri=i; tree[pot].rc=i; tree[i].val=map[pot][i]; }
/// CreateTree(i);///这样子找到一个孩子就直接建树或者是找到两个孩子再建树都可以的!
}
} if(li)CreateTree(li);///递归建树
if(ri)CreateTree(ri);///递归建树
}
int TreeDP(int pot,int e)
{///dp,树形DP
if(!pot||!e)return 0;
if(tree[pot].lc==0)return tree[pot].val;///叶子几节点
if(dp[pot][e])return dp[pot][e];///这一行没有的话会死循环
int mmax=0;
for(int i=0;i<e;++i)
{
int lnum=TreeDP(tree[pot].lc,i);
int rnum=TreeDP(tree[pot].rc,e-i-1);
mmax=max(mmax,lnum+rnum);
}
dp[pot][e]=mmax+tree[pot].val;///必须要加上tree[pot].val 否则地步无法向上传递
// cout<<"ok:"<<dp[pot][e]<<endl;
return dp[pot][e];
}
void init()
{
memset(dp,0,sizeof(dp));
memset(map,0,sizeof(map));
memset(vis,0,sizeof(vis));
memset(tree,0,sizeof(tree));
}
int main()
{
init();
scanf("%d%d",&n,&q);
int u,v,num;
for(int i=1;i<n;++i)
{
scanf("%d%d%d",&u,&v,&num);
map[u][v]=map[v][u]=num;
}
CreateTree(1);
cout<<TreeDP(1,q+1)<<endl;///因为把权值都下放到点上了,所以点数应该比边数大一,因为还有子节点
/// cout<<dp[1][q]<<endl;///注意这里输出的应该是dp[1][q+1] 因为点数比边大1
return 0;
}
1020. Rope
///给n个点,按照 The nails are described either in a clockwise or in a counterclockwise order starting from an arbitrary nai
///但是每个钉子是一个圆形,也得计算进去,其实直接计算所构成的多变形的边长再加上一个圆的周长就好了,因为多边形的各个角正好对应360°
#include <queue>
#include <stack>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <limits.h>
#include <string.h>
#include <algorithm>
#include<cmath>
using namespace std;
int n;
double r;
///double pai=3.141592;
const double pai = acos(-1.0);
double dis(double x,double y,double x1,double y1)
{
return sqrt( (x-x1)*(x-x1)+(y-y1)*(y-y1) );
}
int main()
{
while(~(scanf("%d%lf",&n,&r)))
{
double ans=0.0;
double x[105],y[105];//,x1,y1,tx,ty;
scanf("%lf%lf",&x[0],&y[0]);
for(int i=1;i<n;++i)
{///我的是读数据和处理一块处理,方便
scanf("%lf%lf",&x[i],&y[i]);
if(i==n-1)ans+=dis(x[i],y[i],x[0],y[0]);
ans+=dis(x[i],y[i],x[i-1],y[i-1]);
}if(n!=1)ans+=dis(x[n-1],y[n-1],x[0],y[0]);///考虑了N==1的情况!其实多次一举,因为本身到本身的距离为0,
///但是这样处理的思想很好!
ans+=pai*r*2;
printf("%.2lf\n",ans);
}
return 0;
}
const double pi = acos(-1.0);
const int MAX = 110;
struct point{ double x,y;};
point p[MAX];
double disp2p(point a,point b)
{
return sqrt( ( a.x - b.x ) * ( a.x - b.x ) + ( a.y - b.y ) * ( a.y - b.y ) );
}
int main()
{
int n;
double r;
while( ~scanf("%d%lf",&n,&r) )
{
for(int i=0; i<n; i++)
scanf("%lf%lf",&p[i].x,&p[i].y);
double sum = 0.0;
for(int i=0; i<n; i++)
sum += disp2p(p[i],p[(i+1)%n]);///先读完数据在处理很OK但是有点小浪费时间
printf("%.2lf\n",sum+2*pi*r);
}
return 0;
}
1021. Sacrament of the Sum
#include<algorithm>
#include <iostream>
#include <cmath>
#include<cstring>
using namespace std;
const int key=10000;
int n1,n2;
int num1[50005],num2[50005];
int sum1[50000],sum2[50000];
int sum3[50000],sum4[50000];
int main()
{
memset(num1,0,sizeof(num1));
memset(num2,0,sizeof(num2));
memset(sum1,0,sizeof(sum1));
memset(sum2,0,sizeof(sum2));
memset(sum3,0,sizeof(sum1));
memset(sum4,0,sizeof(sum2));
cin>>n1;
for(int i=0;i<n1;++i)
{
cin>>num1[i];
if(num1[i]>=0)
{
sum1[num1[i]]=1;
}else sum2[-num1[i]]=1;
}
cin>>n2;
for(int i=0;i<n2;++i)
{
cin>>num2[i];
if(num2[i]>=0)
{
sum3[num2[i]]=1;
}else sum4[-num2[i]]=1;
}
bool bo=false;
for(int i=0;i<n1;++i)
{
if(num1[i]>=key)
{
if(sum4[num1[i]-key]){bo=true;break;}
}else if(num1[i]<key)
{
if(sum3[key-num1[i]]){bo=true;break;}
}else
{
if(sum3[num2[i]+key]){bo=true;break;}
}
}
// cout<<sum1[10424]<<endl;
// cout<<sum4[424]<<endl;
if(bo)cout<<"YES"<<endl;
else cout<<"NO"<<endl;
return 0;
}
#include<iostream>
#include<cstdio>
using namespace std;
const int MAXN=50005;
int main()
{
// freopen("data.in","r",stdin);
// freopen("data.out","w",stdout);
int c,cc,num[MAXN];
cin >> c;
for (int i=0;i<c;++i) cin >> num[i];
num[c]=31440461;
cin >> cc;
int p=0;
for (int i=0;i<cc;++i)
{
int x;
cin >> x;
while (x+num[p]<10000) ++p;
if (x+num[p]==10000) { cout << "YES\n"; return 0; }
}
cout << "NO\n";
return 0;
}
http://www.cnblogs.com/staginner/archive/2012/05/02/2478856.html
/*
可以将问题等效成对于x查找10000-x是否在列表中出现过,二分、哈希等都可以。
*/
#include<stdio.h>
#include<string.h>
#define D 33000
#define MAXD 66000
#define MIN -32768
#define MAX 32767
int N, h[MAXD];
void init()
{
int i, k;
memset(h, 0, sizeof(h));
for(i = 0; i < N; i ++)
{
scanf("%d", &k);
h[D + k] = 1;
}
}
void solve()
{
int i, j, k, ok = 0;
scanf("%d", &N);
for(i = 0; i < N; i ++)
{
scanf("%d", &k);
k = 10000 - k;
if(k >= MIN && k <= MAX && h[D + k])
ok = 1;
}
printf("%s\n", ok ? "YES" : "NO");
}
int main()
{
while(scanf("%d", &N) == 1)
{
init();
solve();
}
return 0;
}
1022. Genealogical Tree
#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
const int N=10000004;
int map[120][120];
int cnt[120];
int n;
queue<int> que;
int ans[110];
int tot;
void f()
{
for(int i=1;i<=n;++i)
{
if(cnt[i]==0)
{
que.push(i);
cnt[i]=-1;
}
}
while(!que.empty())
{
int x=que.front();que.pop();
ans[tot++]=x;
for(int i=1;i<=n;++i)
{
// cout<<i<<" "<<x<<" "<<map[i][x]<<endl;
if(map[i][x])
{//cout<<"hahah"<<endl;
map[i][x]=0;
cnt[i]--;
}
}
for(int i=1;i<=n;++i)
{
if(cnt[i]==0)
{
que.push(i);
cnt[i]=-1;
}
}
}
}
int main()
{
memset(map,0,sizeof(map));
memset(cnt,0,sizeof(cnt));
while(cin>>n)
{
int x;
for(int i=1;i<=n;++i)
{
while(cin>>x)
{
if(x==0)break;;
map[i][x]=1;
cnt[i]++;
}
}
// que.clear();
tot=0;
f(); //cout<<"tot "<<tot<<endl;
if(tot)
{
for(int i=tot-1;i>=0;--i)
cout<<ans[i]<<" ";
cout<<endl;
}else cout<<"jiji"<<endl;
}
return 0;
}
别人的代码,链式前向星:
#include<stdio.h>
#include<string.h>
#define MAXD 110
#define MAXM 10010
int N, cnt, e, first[MAXD], next[MAXM], v[MAXM], topo[MAXD], vis[MAXD];
void add(int x, int y)
{
v[e] = y;
next[e] = first[x], first[x] = e ++;
}
void init()
{
int i, j, k;
memset(first, -1, sizeof(first));
e = 0;
for(i = 1; i <= N; i ++)
for(;;)
{
scanf("%d", &k);
if(k == 0)
break;
add(i, k);
}
}
void dfs(int cur)
{
int i;
vis[cur] = 1;
for(i = first[cur]; i != -1; i = next[i])
if(!vis[v[i]])
dfs(v[i]);
topo[-- cnt] = cur;
}
void solve()
{
int i, j, k;
cnt = N;
for(i = 1; i <= N; i ++)
if(!vis[i])
dfs(i);
printf("%d", topo[0]);
for(i = 1; i < N; i ++)
printf(" %d", topo[i]);
printf("\n");
}
int main()
{
while(scanf("%d", &N) == 1)
{
init();
solve();
}
return 0;
}
1023. Buttons
1025. Democracy in Danger
错误代码, 测试: 4 2 2 2 2 错误输出2或者有的代码输出3
int n;
int num[110];
int main()
{
cin>>n;
for(int i=0;i<n;i++) cin>>num[i];
sort(num,num+n);
int ans=0;
for(int i=0;i<(n+1)/2;++i)
ans+=(num[i]+1)/2;
cout<<ans<<endl;
return 0;
}
for(int i=0;i<(n+2)/2;++i)
ans+=(num[i]+2)/2; /// 这是正确的更改! 4 2 2 2 2 正确输出为6
for(i=0;i<=k/2;i++)
{///比较好理解的的解法
sum+=arr[i]/2+1;
}
1028. Stars
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
#define N 32010
int n;
int ans[N];
int c[N];
int lowbit(int x)
{
return x&(-x);
}
void update(int x)
{
while(x<=N)
{
c[x]++;
x+=lowbit(x);
}
}
int getsum(int x)
{
int ans=0;
while(x>0)
{
ans+=c[x];
x-=lowbit(x);
}
return ans;
}
int main()
{
while(scanf("%d",&n)!=EOF)
{
memset(c,0,sizeof(c));
memset(ans,0,sizeof(ans));
int x,y;
for(int i=0; i<n; ++i)
{
scanf("%d%d",&x,&y);
int t=getsum(x+1);///这里必须是x+1,因为数据中x会等于0,这样导致树状数组无法处理,导致
///超时超时超时超时超时超时……
ans[t]++;
update(x+1);
}
for(int i=0; i<n; ++i)
printf("%d\n",ans[i]);
}
return 0;
}
1033. Labyrinth
#include<iostream>
#include<queue>
#include<cstring>
using namespace std;
char map[35][35];
int n;
struct Node
{///便于封装放到队列里面!
int x,y;
char ch;
};
queue <Node> que;
int vis[35][35];
int dir[4][2]={0,1, 0,-1, 1,0 , -1,0 };
bool isok(int x,int y)
{
if( x>=0&&x<n&&y>=0&&y<n )return true;
return false;
}
int ans;
int bfs(int x0,int y0)
{
ans=0;
memset(vis,0,sizeof(vis));
vis[x0][y0]=1;
Node t;
t.x=x0; t.y=y0; t.ch=map[x0][y0];
que.push(t);
while(!que.empty())
{
t=que.front();que.pop();
vis[t.x][t.y]=1;
for(int i=0;i<4;++i)
{
Node tmp; tmp.x=t.x+dir[i][0];
tmp.y=t.y+dir[i][1];
if(!isok(tmp.x,tmp.y))
{
ans++;continue;
}
if(isok(tmp.x,tmp.y)&&!vis[tmp.x][tmp.y])
{
if(map[tmp.x][tmp.y]=='#')ans++;
else
{
tmp.ch=map[tmp.x][tmp.y];
que.push(tmp);
vis[tmp.x][tmp.y]=1;
}
}
}
}
if(vis[n-1][n-1])return ans;///如果最后一个出口没有被访问,那么在调用一次BFS!
else
{
int cnt=ans;
cnt+=bfs(n-1,n-1);
return cnt;
}
}
int main()
{
while(cin>>n)
{
for(int i=0;i<n;++i)
{
cin>>map[i];
}
int ans1=bfs(0,0);
// int ans2=bfs(n-1,n-1);
cout<<(ans1-4)*9<<endl;///为什么要-4? 因为两个路口那里算重了两次!
}
return 0;
}
下面附上Domacles的代码,比较漂亮的DFS
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
using namespace std;
int x[4]= {1,-1,0,0};
int y[4]= {0,0,1,-1};
int n;
char Map[35][35]= {0};
int path[35][35]= {0};///数组至少是35,多于的一圈做哨兵!! 而且省了isok函数
int ans=0;
/*
这里的DFS没有回溯,但是也能够遍历!
没有漏掉,这是我一直不放心的地方!
*/
void DFS(int X,int Y)
{
int i;
path[X][Y]=1;
for(i=0; i<4; i++)
{
if(Map[X+x[i]][Y+y[i]]=='.'&&path[X+x[i]][Y+y[i]]==0)
DFS(X+x[i],Y+y[i]);
else if(Map[X+x[i]][Y+y[i]]=='#')
ans++;
}
}
void read()
{
int j,k;
string s;
scanf("%d",&n);
memset(Map,'#',sizeof(Map));
for(j=1; j<=n; j++)
{
cin>>s;
for(k=1; k<=n; k++)
Map[j][k]=s[k-1];
}
}
void print()
{
printf("%d\n",(ans-4)*9);
}
int main()
{
read();
DFS(1,1);
if(path[n][n]==0)
DFS(n,n);
print();
return 0;
}
1044. Lucky Tickets. Easy!
#include<algorithm>
#include <iostream>
#include <cmath>
#include<cstring>
using namespace std;
int n;
int num[2000];
void f (int x,int ceng)
{
for(int i=0; i<10; ++i)
{
if(ceng==n) num[x+i]++;
else f(x+i,ceng+1);
}
}
int main()
{
memset(num,0,sizeof(num));
cin>>n;
n/=2;
f(0,1);
int a=0;
for(int i=0; i<=45; ++i)///最多45
a+=(num[i]*num[i]);
cout<<a<<endl;
return 0;
}
分类枚举的思路,以n=4为例:
void f4()
{///这是4位的情况! 枚举2位,后面的2位和前面的一样!
int count=0;
for(int i1=0; i1<=9; i1++)
for(int i2=0; i2<=9; i2++)
num[i1+i2]++;
int ans=0;
for(int i=0;i<=45;++i)
ans+=(num[i]*num[i]);
cout<<count<<endl;
}
下面是别人的代码(自己还需研究):
#include<iostream>
using namespace std;
int A[5][45];
int tot,n;
int main()
{
int i,j,k;
scanf("%d",&n);
n/=2;
A[0][0]=1;
for(i=0;i<n;i++)
for(k=0;k<=i*9;k++)
for(j=0;j<10;j++)
A[i+1][k+j]+=A[i][k];
for(i=0;i<=n*9;i++)
tot+=A[n][i]*A[n][i];
printf("%d/n",tot);
return 0;
}
/*
I: 2 O: 10
I: 4 O: 670
I: 6 O: 55252
I: 8 O: 4816030
*/
1047. Simple Calculations
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
int f[1010];
int n;
double a0,am,c[3010];
double sum[3010];
int main()
{
cin>>n;
cin>>a0>>am;
memset(sum,0,sizeof(sum));
for(int i=1;i<=n;++i)
{
cin>>c[i];
sum[i]=sum[i-1]+c[i];
}
double ans=0;
for(int i=1;i<=n;++i)
{
ans+=sum[i];
}
printf("%.2f\n",(am+n*a0-2*ans)/(n+1));///其实这里的精度控制的不是很好!
return 0;
}
1053. Pinocchio
#include<iostream>
using namespace std;
int gcd(int a,int b)
{
if(a%b==0)return b;
else gcd(b,a%b);///不加return 总感觉是错的,但是还是A了……
}
int main()
{
int n;
cin>>n;int a[n];
for(int i=0;i<n;++i)cin>>a[i];
for(int i=n-1;i>0;i--)a[i-1]=gcd(a[i],a[i-1]);
cout<<a[0]<<endl;
return 0;
}
1068. Sum
给一个n,然后求1+2+……+n 注意正负数!
1073. Square Country
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
int k,ans;
int que[300];
int tot;
void init()
{
tot=0; que[0]=0;
for(int i=1;que[tot-1]<=60000;i++)
que[tot++]=i*i;
}
int main()
{
init();
int n;cin>>n;
int dp[n];
memset(dp,0,sizeof(dp));///注意这里初始化时0
dp[0]=1;
for(int i=1;i<=n;++i)
{
for(int j=0;j<tot;++j)
{///完全背包的思想
if(i>=que[j]&&dp[i-que[j]])
{
if(dp[i])
{//if(i==344&&dp[i-que[j]]+1<dp[i])cout<<que[j]<<endl;;
dp[i]=min(dp[i-que[j]]+1,dp[i]);
}else
{
dp[i]=dp[i-que[j]]+1;///注意这里忘记加1的话……
//cout<<que[j]<<endl;
}
}
}
}
cout<<dp[n]-1<<endl;///注意这里为什么减1
return 0;
}
1079. Maximum
- a0 = 0
- a1 = 1
- a2i = ai
- a2i+1 = ai + ai+1
1080. Map Coloring
”图的染色问题,类似二分图的染色问题。其实这题就是问你能不能类似二分图一样把图染成两个颜色,而且相邻顶点颜色不一样。
直接DFS。。。没啥好说的。如果遇到不合适的,输出-1.“
DFS遍历的过程中遇到一个点设成1,下一个点就设成0;同时记录在ans里面,随时判断相邻的点ans是否相同,相同则不合适……
注意图的链式前向星和树的链式前向星不一样…… 如何避免重复!!……
#include<iostream>
#include<cstring>
using namespace std;
struct Edge
{
int u,v;
int val;
int next;
}edg[100*100];
int head[100];
int tot;
void addEdge(int u,int v)
{
edg[tot].v=v;
edg[tot].next=head[u];
head[u]=tot++;
}
int n;
int ans[105];
bool flag=0;
void DFS(int x,int f,int e)
{///如何避免死循环呢?!!!! 以前做过的题用不会放父节点的方式便面重复而这里不行,因为这是图,而那次是树,树和图终究还是有区别的!
if(flag)return;
e=(e==0?1:0);
if(x==1)ans[x]=0;
else ans[x]=e;
for(int i=head[x];i!=-1;i=edg[i].next)
{
int v=edg[i].v;
// if(v!=f)
// {
if(ans[v]==ans[x]){flag=1;return ;}///表示冲突了
else if(ans[v]==-1)DFS(v,x,e);///???!!!!!如果不是这样就会死循环…… 先超内存再超时……
///图的DFS就得设访问标志灯避免重复,而树则可以不必,他可以设置不回访父节点就好了
//}
}
}
int main()
{
memset(head,-1,sizeof(head));
memset(ans,-1,sizeof(ans));
tot=0;
cin>>n;
for(int i=1;i<=n;++i)
{
int t;
while(cin>>t&&t)
{
addEdge(i,t);
addEdge(t,i);
}
}
DFS(1,1,1);
if(flag){cout<<-1<<endl;return 0;}
for(int i=1;i<=n;++i)///加上这一for是为了避免整个图不是一个联通块来说的,但好像没有这样的测试数据!
if(ans[i]==-1)DFS(i,i,1);
if(flag){cout<<-1<<endl;return 0;}
for(int i=1;i<=n;++i)cout<<ans[i];
cout<<endl;
return 0;
}
1082. Gaby Ivanushka
#include <stdio.h>
using namespace std;
#define N 10
long c;
long A[N];
long P(long l, long r)
{
long x=A[l],
i=l-1,
j=r+1,t;
while(1)
{
do
{
--j;
++c;
}
while(A[j]>x);
do
{
// printf("%s\n","ok");
++i;
++c;
}
while(A[i]<x);
if(i<j)
{
t=A[i];
A[i]=A[j];
A[j]=t;
}
else return j;
}
}
void Q(long l, long r)
{
long n;
if(l<r)
{
n=P(l,r);
Q(l,n);
Q(n+1,r);
}
}
int main(void)
{
printf("Please cin %d number:\n",N);
c=0;
for(long i=0; i<N; ++i)
scanf("%ld", &A[i]);
Q(0,N-1);
if(c==(N*N+3*N-4)/2)
{
printf
("Beutiful Vasilisa");
// printf(" %d",c);
}
else printf
("Immortal Koshcei");
return 0;
}
1083. Factorials!!!
1084. Goat in the Garden
给一个正方形的草坪中,在中间有一个stake,拴着一只goat,问羊能吃到的草的最大面积是多少,保留三位小数!
分三种情况,圆较小,全部在草坪内部; 一部分在草坪外部;或者全部把草坪包围了……
这是计算几何题,貌似是入门题! 但对于我这个计算几何菜鸟来说是一窍不通!
http://blog.csdn.net/zxy_snow/article/details/6407157 先保留小媛的解题报告!
1086. Cryptography
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=10000004;
int num[N];
bool isprime[N];
int prime[N];
int tot;
void init()
{
memset(isprime,true,sizeof(isprime));
isprime[0]=isprime[1]=false;
for(int i=2; i<N; ++i)if(isprime[i])
{
prime[++tot]=i;
for(int j=i*2;j<N;j+=i)
isprime[j]=false;
}
}
int main()
{
init();
int n;
while(cin>>n)
{
int x;
for(int i=0;i<n;++i)
{
cin>>x;
cout<<prime[x]<<endl;
}
}
return 0;
}
1087. The Time to Take Stones
一堆石头,每人每次只能取走k[i]个! 谁取走最后一个谁就是输家!
怎么办呢?! 既然分类是game,就得有博弈中的必败态必胜态相互转移! 呵呵,既然转移很多时候就可以用到动态规划……!
因为每个状态转化而来的路径不一样 ,因为K[i]有嘛,怎么办呢?!! 记住题意,按最优方式去取石头,如果一个人从一个状态可以转化到下一个状态,那么他想转化到的下一个状态是什么呢?! 当然是必败态了,如果能转化到的所有状态里面有一个是必败态,那就OK了,如果一个也没有,抱歉…… 那么突破点在哪里呢?! 当然是最后那块石头了…… 用discuss上的一句话叫做bottom-up DP; 注意边界的处理,dp[n]是必胜还是必败,设置的时候设置成取这个还是取完这个!
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
int n,m;
int k[60];
int dp[10010];
int main()
{
cin>>n>>m;
for(int i=1;i<=m;++i)
cin>>k[i];
memset(dp,0,sizeof(dp));
sort(k+1,k+m+1);
for(int i=n;i>=1;--i)
{
for(int j=1;j<=m;++j) if(dp[i]==0&&i>=k[j])dp[i-k[j]]=1;
}
if(dp[1])cout<<1<<endl;
else cout<<2<<endl;
return 0;
}