1. 程式人生 > >POJ-2586盈虧問題多種思路

POJ-2586盈虧問題多種思路

題目概述

英文題目不是很容易懂,拜了各位大佬碼頭後才看明白,大意是一個公司每月盈利和虧損的金額是確定的,分別為s和d,輸入格式是每行兩個數,然而此公司連續的五個月其收益綜合必定是虧損的。求此公司一年下來能否盈利,若能求出最大的盈利額,若否,輸出Deficit。

題目分析

  • 還是太嫩了,看到題目是貪心的,結果也想不出拿哪個值做key,再排序後依次處理。思維就陷入僵局了。看了各位大佬的分析後才發現自己的愚蠢之處。若是實在不會,這個題資料量比較小,直接列舉也可以的, 2^12才4k數量級。
  • 還有這個題目也偏模擬類了,不一定非要用什麼嚴謹的演算法,體現貪心的思想是關鍵,甚至還有點回溯的感覺
    。先假設所有月份均盈利,再回退檢查,若連續五個月總收益為正則將最後一個月設為虧損。一年有8的連續的五個月,最多回退5次,即全部虧損(一個月的盈利大於四個月的虧損時),只需8*5次判斷。
  • 用分類討論的方法也很有效,注意要把虧損放到儘可能偏中間的月份(s->surplus;d->deficit)
    • 分類 每月安排 總結果
    • 4s<1d ssssdssssdss 10s-2d
    • 3s<2d sssddsssddss 8s-4d
    • 2s<3d ssdddssdddss 6s-6d
    • 1s<4d sddddsddddsd 3s-9d
    • else dddddddddddd deficit

程式碼實現(貪心+回溯+模擬)

#include <iostream>
#include <stdio.h>
#include <algorithm>
using namespace std;

int month[12] = {0};

int check(int s){
	int sum = 0;
	for (int i=0; i<5; i++){
		sum += month[s+i];
	}
	return sum>0;
}
//void show(){
//	for (int i=0; i<12; i++){
// cout<<month[i]<<" "; // } // cout<<endl; //} int main(){ int s, d, res; while(cin>>s>>d){ fill(month, month+12, s); // show(); for (int i=0; i<8; i++){ for(int j=0; j<5; j++){ if (check(i)){ month[i+4-j] = -d; } } // show(); } int sum=0; for (int i=0; i<12; i++){ sum += month[i]; } if (sum > 0){ cout<<sum<<endl; }else{ cout<<"Deficit"<<endl; } } return 0; }