lvshengwei  
日历
<2026年6月>
31123456
78910111213
14151617181920
21222324252627
2829301234
567891011
统计
  • 随笔 - 0
  • 文章 - 4
  • 评论 - 0
  • 引用 - 0

导航

常用链接

留言簿

文章档案

搜索

  •  

最新评论

 

/*终于又开始写了,本来打算按上课的顺序写,但是发现不够有条理,于是先写基础算法*/
一、分治;
  将一个规模为N的问题分解为K个规模较小的子问题,这些子问题相互独立且与原问题性质相同。
  //子问题如果有交集且无后效性就是动态规划了;
  问题:给定两个数a、b,计算'1'在a、b之间出现的次数。0 0 为结束标记(范围0<a,b<100,000,000)
input:
1 10
44 497
346 542
1199 1748
1496 1403
0 0
output:
2
185
40
666
113
代码:
#include <fstream>
using namespace std;
ifstream cin("1_1.in");
ofstream cout("1_1.out");
int d[11];
int value,i;
void deal(int n)
{
    if(n<=0)return;
    int one,ten;
    one=n%10;
    n/=10;
    ten=n;
    for(i=0;i<one;i++)d[i]+=value;
    while(ten)
    {
        d[ten%10]+=(one+1)*value;
        ten/=10;
    }
    for(i=0;i<10;i++)d[i]+=value*n;
    d[0]-=value;
    value*=10;
    deal(n-1);
}
int main()
{
    int i;
    int a,b;
    while(cin>>a>>b)
    {
        if(a==0&&b==0)break;
        if(a<b)swap(a,b);
        for(i=0;i<10;i++)d[i]=0;
        value=1;
        deal(a);
        value=-1;
        deal(b-1);
        cout<<d[1]<<endl;
    }
    //system ("pause");
    return 0;
}
//当然把最后的d[1]改一下也可以记录随便某数的出现次数;重点是void deal(int n);

二、递归(调用自身);
经典问题:Hanoi塔;
input : 3
output:
move 1 from a to c
move 2 from a to b
move 1 from c to b
move 3 from a to c
move 1 from b to a
move 2 from b to c
move 1 from a to c
代码:
#include <fstream>
using namespace std;
ifstream cin("hanoi.in");
ofstream cout("hanoi.out");
void move(int n,char x,char y)
{
    cout<<"move "<<n<<" from "<<x<<" to "<<y<<endl;
}
void hanoi(int n,char a,char b,char c)
{
    if(n==1)move(1,a,c);
    else
    {
        hanoi(n-1,a,c,b);
        move(n,a,c);
        hanoi(n-1,b,a,c);
    }
}
int main()
{
    int n;
    cin>>n;
    hanoi(n,'a','b','c');
    //system ("pause");
    return 0;
}
  
三、枚举(遍历所有可能解再排除错误);
题目:木棒三角形;
      输入木棒总数和长度,挑三根组成直角三角形,输出最大面积。组不成输出"error";
input:
4
1 2 3 4
5
2 3 4 5 6
6
3 4 5 6 8 10
2
1 1
output:
error
6
24
error
代码:
#include <fstream>
using namespace std;
ifstream cin("1_3.in");
ofstream cout("1_3.out");
int main()
{
    int i,j,k,n;
    double ans;
    int len[110];
    while(cin>>n)
    {
        for(i=1;i<=n;i++)cin>>len[i];
        ans=-1;
        for(i=1;i<=n;i++)
            for(j=i+1;j<=n;j++)
                for(k=j+1;k<=n;k++)
                    if(len[i]*len[i]+len[j]*len[j]==len[k]*len[k])
                        if(0.5*len[i]*len[j]>ans)ans=0.5*len[i]*len[j];
    if(ans==-1)cout<<"error"<<endl;
    else cout<<ans<<endl;
    }
    //system ("pause");
    return 0;
}

四、贪心(每步只找一个最优解);
问题:
A公司的电脑管理系统受到了千年虫病毒的攻击,A公司因此丢失了向MS公司做年终汇报的数据。
A公司目前掌握的数据是MS公司每次公布的公司盈亏报表,而MS公司公布盈亏的方式与众不同,它每次都是将连续5个月的盈或亏得总和做一次性的公布,因此A公司不知道每个月具体的盈亏状况。已知的情况是所有盈利月盈利固定为s,而亏损月亏损固定为d。
写一个程序,确定MS公司是否盈利,若盈利的话,那么可能的盈利最大值是多少。
Input
输入为两个正整数s和d。
Output
对于每一组的输入数据,若盈利的话,那么输出可能的盈利最大值是多少;若亏损的话,输出Deficit。
input:
59 237
375 743
200000 849694
2500000 8000000
output:
116
28
300612
Deficit
代码:
#include <fstream>
using namespace std;
ifstream cin("1_4.in");
ofstream cout("1_4.out");
int main()
{
    int i,ans;
    int s,d;
    while(cin>>s>>d)
    {
        for(i=1;i<=5;i++)
            if(s*(5-i)-d*i<0)break;
        if(i==4)ans=3*s-9*d;
        else ans=s*(12-2*i)-d*2*i;
        if(i==5||ans<0)cout<<"Deficit"<<endl;
        else cout<<ans<<endl;
    }
    //system ("pause");
    return 0;
}
//另有一普及组题目;
排座椅(seat.pas/c/cpp)
【问题描述】
上课的时候总有一些同学和前后左右的人交头接耳,这是令小学班主任十分头疼的一件事情。不过,班主任小雪发现了一些有趣的现象,当同学们的座次确定下来之后,只有有限的D对同学上课时会交头接耳。同学们在教室中坐成了M行N列,坐在第i行第j列的同学的位置是(i,j),为了方便同学们进出,在教室中设置了K条横向的通道,L条纵向的通道。于是,聪明的小雪想到了一个办法,或许可以减少上课时学生交头接耳的问题:她打算重新摆放桌椅,改变同学们桌椅间通道的位置,因为如果一条通道隔开了两个会交头接耳的同学,那么他们就不会交头接耳了。
请你帮忙给小雪编写一个程序,给出最好的通道划分方案。在该方案下,上课时交头接耳的学生对数最少。
【输入】
输入文件seat.in的第一行,有5各用空格隔开的整数,分别是M,N,K,L,D(2<=N,M<=1000,0<=K<M,0<=L<N,D<=2000)。
接下来D行,每行有4个用空格隔开的整数,第i行的4个整数Xi,Yi,Pi,Qi,表示坐在位置(Xi,Yi)与(Pi,Qi)的两个同学会交头接耳(输入保证他们前后相邻或者左右相邻)。
输入数据保证最优方案的唯一性。
【输出】
输出文件seat.out共两行。
第一行包含K个整数,a1a2……aK,表示第a1行和a1+1行之间、第a2行和第a2+1行之间、…、第aK行和第aK+1行之间要开辟通道,其中ai< ai+1,每两个整数之间用空格隔开(行尾没有空格)。
第二行包含L个整数,b1b2……bk,表示第b1列和b1+1列之间、第b2列和第b2+1列之间、…、第bL列和第bL+1列之间要开辟通道,其中bi< bi+1,每两个整数之间用空格隔开(行尾没有空格)。
【输入输出样例】
seat.in 
4 5 1 2 3
4 2 4 3
2 3 3 3
2 5 2 4 
seat.out
2
2 4

上图中用符号*、※、+ 标出了3对会交头接耳的学生的位置,图中3条粗线的位置表示通道,图示的通道划分方案是唯一的最佳方案。
代码:
#include <fstream>
using namespace std;
ifstream cin("seat.in");
ofstream cout("seat.out");
int main()
{
  int y[1010],x[1010],w[1010];
  int m,n,k,l,d;
  int x1,y1,x2,y2;
  int i,j;
  cin>>m>>n>>k>>l>>d;
  for(i=1;i<=m;i++)y[i]=0;
  for(i=1;i<=n;i++)x[i]=0;
  for(i=0;i<d;i++)
  {
    cin>>y1>>x1>>y2>>x2;
    if(x1==x2)
    {
      if(y1>y2)swap(y1,y2);
      y[y1]++;
    }
    else
      if(y1==y2)
      {
        if(x1>x2)swap(x1,x2);
        x[x1]++;
      }
  }
  //y
  for(i=0;i<=m;i++)
    w[i]=i;
  for(i=1;i<m;i++)
    for(j=i+1;j<=m;j++)
      if(y[i]<y[j])
      {
        swap(y[i],y[j]);
        swap(w[i],w[j]);
      }
  for(i=1;i<k;i++)
    for(j=i+1;j<=k;j++)
      if(w[i]>w[j])
        swap(w[i],w[j]);
  cout<<w[1];
  for(i=2;i<=k;i++)cout<<" "<<w[i];
  cout<<endl;
  //x
  for(i=0;i<=n;i++)w[i]=i;
  for(i=1;i<n;i++)
    for(j=i+1;j<=n;j++)
      if(x[i]<x[j])
      {
        swap(x[i],x[j]);
        swap(w[i],w[j]);
      }
  for(i=1;i<l;i++)
    for(j=i+1;j<=l;j++)
      if(w[i]>w[j])swap(w[i],w[j]);
  cout<<w[1];
  for(i=2;i<=l;i++)cout<<" "<<w[i];
  cout << endl;
  //system ("pause");
  return 0;

//在marcool上评测终于通过了!!!
return 0;

posted on 2012-07-30 19:05 Samuel-Lv 阅读(156) 评论(0)  编辑 收藏 引用

只有注册用户登录后才能发表评论。
网站导航:   博客园   博客园最新博文   博问   管理


 
Copyright © Samuel-Lv Powered by: 博客园 模板提供:沪江博客